From b471fa3885b149a49d24043df75fc4a83a4dde33 Mon Sep 17 00:00:00 2001 From: Andreas Tille Date: Fri, 20 Dec 2019 10:27:03 +0000 Subject: [PATCH] Import pbbam_1.0.6+dfsg.orig.tar.xz [dgit import orig pbbam_1.0.6+dfsg.orig.tar.xz] --- .clang-format | 13 + .gitignore | 9 + .travis.yml | 61 + CHANGELOG.md | 621 + INSTALL.md | 3 + LICENSE.txt | 34 + README.md | 62 + bamboo_build.sh | 54 + docs/Doxyfile.in | 1602 +++ docs/Makefile | 168 + docs/examples/code/BarcodeQuery.txt | 17 + docs/examples/code/Compare.txt | 3 + docs/examples/code/Compare_AlignedEnd.txt | 2 + docs/examples/code/Compare_AlignedStart.txt | 2 + docs/examples/code/Compare_AlignedStrand.txt | 2 + docs/examples/code/Compare_BarcodeForward.txt | 2 + docs/examples/code/Compare_BarcodeQuality.txt | 2 + docs/examples/code/Compare_BarcodeReverse.txt | 2 + docs/examples/code/Compare_FullName.txt | 2 + .../code/Compare_LocalContextFlag.txt | 2 + docs/examples/code/Compare_MapQuality.txt | 2 + docs/examples/code/Compare_MovieName.txt | 2 + .../examples/code/Compare_NumDeletedBases.txt | 2 + .../code/Compare_NumInsertedBases.txt | 2 + docs/examples/code/Compare_NumMatches.txt | 2 + docs/examples/code/Compare_NumMismatches.txt | 2 + docs/examples/code/Compare_QueryEnd.txt | 2 + docs/examples/code/Compare_QueryStart.txt | 2 + docs/examples/code/Compare_ReadAccuracy.txt | 2 + docs/examples/code/Compare_ReadGroupId.txt | 2 + .../code/Compare_ReadGroupNumericId.txt | 2 + docs/examples/code/Compare_ReferenceEnd.txt | 2 + docs/examples/code/Compare_ReferenceId.txt | 2 + docs/examples/code/Compare_ReferenceName.txt | 2 + docs/examples/code/Compare_ReferenceStart.txt | 2 + .../code/Compare_TypeFromOperator.txt | 2 + docs/examples/code/Compare_TypeToName.txt | 2 + docs/examples/code/Compare_Zmw.txt | 2 + docs/examples/code/EntireFileQuery.txt | 15 + .../code/EntireFileQuery_BamFilename.txt | 4 + .../code/EntireFileQuery_NonConst.txt | 4 + docs/examples/code/GenomicIntervalQuery.txt | 16 + .../code/GenomicIntervalQuery_Reuse.txt | 8 + docs/examples/code/PbiAlignedEndFilter.txt | 4 + docs/examples/code/PbiAlignedLengthFilter.txt | 4 + docs/examples/code/PbiAlignedStartFilter.txt | 4 + docs/examples/code/PbiAlignedStrandFilter.txt | 5 + docs/examples/code/PbiBarcodeFilter.txt | 17 + .../examples/code/PbiBarcodeForwardFilter.txt | 15 + .../examples/code/PbiBarcodeQualityFilter.txt | 5 + .../examples/code/PbiBarcodeReverseFilter.txt | 15 + docs/examples/code/PbiBarcodesFilter.txt | 6 + docs/examples/code/PbiBuilder_WithReader.txt | 30 + docs/examples/code/PbiBuilder_WithWriter.txt | 12 + docs/examples/code/PbiFilterQuery.txt | 22 + docs/examples/code/PbiFilter_Composition.txt | 8 + docs/examples/code/PbiFilter_CustomFilter.txt | 21 + docs/examples/code/PbiFilter_Interface.txt | 1 + docs/examples/code/PbiIdentityFilter.txt | 6 + docs/examples/code/PbiLocalContextFilter.txt | 22 + docs/examples/code/PbiMapQualityFilter.txt | 5 + docs/examples/code/PbiMovieNameFilter.txt | 14 + .../code/PbiNumDeletedBasesFilter.txt | 6 + .../code/PbiNumInsertedBasesFilter.txt | 6 + docs/examples/code/PbiNumMatchesFilter.txt | 6 + docs/examples/code/PbiNumMismatchesFilter.txt | 6 + docs/examples/code/PbiQueryEndFilter.txt | 5 + docs/examples/code/PbiQueryLengthFilter.txt | 5 + docs/examples/code/PbiQueryNameFilter.txt | 15 + docs/examples/code/PbiQueryStartFilter.txt | 5 + docs/examples/code/PbiReadAccuracyFilter.txt | 5 + docs/examples/code/PbiReadGroupFilter.txt | 64 + docs/examples/code/PbiReferenceEndFilter.txt | 5 + docs/examples/code/PbiReferenceIdFilter.txt | 16 + docs/examples/code/PbiReferenceNameFilter.txt | 15 + .../examples/code/PbiReferenceStartFilter.txt | 5 + docs/examples/code/PbiZmwFilter.txt | 16 + docs/examples/code/ReadAccuracyQuery.txt | 15 + docs/examples/code/SubreadLengthQuery.txt | 15 + docs/examples/code/Tag_AsciiCtor.txt | 10 + .../code/WhitelistedZmwReadStitcher.txt | 6 + docs/examples/code/ZmwGroupQuery.txt | 23 + docs/examples/code/ZmwQuery.txt | 6 + .../plaintext/AlignmentPrinterOutput.txt | 13 + .../plaintext/PbiFilter_DataSetXmlFilters.txt | 14 + docs/meson.build | 24 + docs/source/api/Accuracy.rst | 11 + docs/source/api/AlignmentPrinter.rst | 11 + docs/source/api/AlignmentSet.rst | 11 + docs/source/api/BaiIndexedBamReader.rst | 11 + docs/source/api/BamFile.rst | 11 + docs/source/api/BamHeader.rst | 11 + docs/source/api/BamReader.rst | 11 + docs/source/api/BamRecord.rst | 17 + docs/source/api/BamRecordBuilder.rst | 11 + docs/source/api/BamRecordImpl.rst | 11 + docs/source/api/BamRecordView.rst | 11 + docs/source/api/BamTagCodec.rst | 11 + docs/source/api/BamWriter.rst | 11 + docs/source/api/BarcodeQuery.rst | 11 + docs/source/api/BarcodeSet.rst | 11 + docs/source/api/Cigar.rst | 11 + docs/source/api/CigarOperation.rst | 13 + docs/source/api/Compare.rst | 8 + docs/source/api/Config.rst | 8 + docs/source/api/ConsensusAlignmentSet.rst | 11 + docs/source/api/ConsensusReadSet.rst | 11 + docs/source/api/ContigSet.rst | 11 + docs/source/api/DataSet.rst | 11 + docs/source/api/DataSetBase.rst | 11 + docs/source/api/DataSetMetadata.rst | 11 + docs/source/api/EntireFileQuery.rst | 11 + docs/source/api/ExtensionElement.rst | 11 + docs/source/api/Extensions.rst | 11 + docs/source/api/ExternalResource.rst | 11 + docs/source/api/ExternalResources.rst | 11 + docs/source/api/FileIndex.rst | 11 + docs/source/api/FileIndices.rst | 11 + docs/source/api/Filter.rst | 11 + docs/source/api/Filters.rst | 11 + docs/source/api/Frames.rst | 11 + docs/source/api/GenomicInterval.rst | 11 + .../api/GenomicIntervalCompositeBamReader.rst | 11 + docs/source/api/GenomicIntervalQuery.rst | 11 + docs/source/api/HdfSubreadSet.rst | 11 + docs/source/api/IndexResultBlock.rst | 17 + docs/source/api/IndexedFastaReader.rst | 11 + docs/source/api/Interval.rst | 11 + .../InvalidSequencingChemistryException.rst | 11 + docs/source/api/LocalContextFlags.rst | 8 + docs/source/api/NamespaceInfo.rst | 11 + docs/source/api/NamespaceRegistry.rst | 11 + docs/source/api/Orientation.rst | 8 + docs/source/api/ParentTool.rst | 11 + docs/source/api/PbiBuilder.rst | 11 + docs/source/api/PbiFile.rst | 14 + docs/source/api/PbiFilter.rst | 11 + .../api/PbiFilterCompositeBamReader.rst | 11 + docs/source/api/PbiFilterQuery.rst | 11 + docs/source/api/PbiFilterTypes.rst | 8 + docs/source/api/PbiIndexedBamReader.rst | 11 + docs/source/api/PbiRawBarcodeData.rst | 11 + docs/source/api/PbiRawBasicData.rst | 11 + docs/source/api/PbiRawData.rst | 11 + docs/source/api/PbiRawMappedData.rst | 11 + docs/source/api/PbiRawReferenceData.rst | 11 + docs/source/api/PbiReferenceEntry.rst | 11 + docs/source/api/Position.rst | 10 + docs/source/api/ProgramInfo.rst | 11 + docs/source/api/QNameQuery.rst | 11 + docs/source/api/QualityValue.rst | 11 + docs/source/api/QualityValues.rst | 11 + docs/source/api/ReadAccuracyQuery.rst | 11 + docs/source/api/ReadGroupInfo.rst | 21 + docs/source/api/ReferenceSet.rst | 11 + docs/source/api/SamTagCodec.rst | 11 + docs/source/api/SequenceInfo.rst | 11 + .../api/SequentialCompositeBamReader.rst | 11 + docs/source/api/Strand.rst | 8 + docs/source/api/SubDataSets.rst | 11 + docs/source/api/SubreadLengthQuery.rst | 11 + docs/source/api/SubreadSet.rst | 11 + docs/source/api/Tag.rst | 15 + docs/source/api/TagCollection.rst | 11 + .../source/api/VirtualPolymeraseBamRecord.rst | 11 + .../api/VirtualPolymeraseCompositeReader.rst | 11 + docs/source/api/VirtualPolymeraseReader.rst | 11 + docs/source/api/VirtualRegion.rst | 11 + docs/source/api/VirtualRegionType.rst | 8 + docs/source/api/VirtualRegionTypeMap.rst | 11 + docs/source/api/ZmwGroupQuery.rst | 11 + docs/source/api/ZmwQuery.rst | 11 + docs/source/api/ZmwWhitelistVirtualReader.rst | 11 + docs/source/api_reference.rst | 12 + docs/source/commandline_utilities.rst | 15 + docs/source/conf.py | 332 + docs/source/getting_started.rst | 105 + docs/source/index.rst | 33 + .../pacbio-theme/static/headerGradient.jpg | Bin 0 -> 7099 bytes docs/source/pacbio-theme/static/pacbio.css | 238 + .../source/pacbio-theme/static/pacbioLogo.png | Bin 0 -> 3128 bytes docs/source/pacbio-theme/static/pygments.css | 55 + docs/source/pacbio-theme/theme.conf | 4 + docs/source/requirements.txt | 1 + docs/source/tools/bam2sam.rst | 21 + docs/source/tools/pbindex.rst | 18 + docs/source/tools/pbindexdump.rst | 233 + docs/source/tools/pbmerge.rst | 30 + docs/specs/pbbam.rst | 630 + docs/specs/pbbam_structure.png | Bin 0 -> 23521 bytes docs/specs/pbbam_updated_release3_2.rst | 618 + include/meson.build | 165 + include/pbbam/Accuracy.h | 22 + include/pbbam/AlignmentPrinter.h | 71 + include/pbbam/BaiIndexCache.h | 60 + include/pbbam/BaiIndexedBamReader.h | 115 + include/pbbam/BamFile.h | 183 + include/pbbam/BamFileMerger.h | 61 + include/pbbam/BamHeader.h | 384 + include/pbbam/BamReader.h | 152 + include/pbbam/BamRecord.h | 1314 ++ include/pbbam/BamRecordBuilder.h | 239 + include/pbbam/BamRecordImpl.h | 594 + include/pbbam/BamRecordTag.h | 64 + include/pbbam/BamRecordView.h | 132 + include/pbbam/BamTagCodec.h | 92 + include/pbbam/BamWriter.h | 220 + include/pbbam/BarcodeQuery.h | 64 + include/pbbam/BgzipFastaWriter.h | 47 + include/pbbam/BgzipFastqWriter.h | 50 + include/pbbam/BgzipWriter.h | 81 + include/pbbam/Cigar.h | 29 + include/pbbam/CigarOperation.h | 29 + include/pbbam/ClipType.h | 32 + include/pbbam/Compare.h | 471 + include/pbbam/CompositeBamReader.h | 286 + include/pbbam/CompositeFastaReader.h | 63 + include/pbbam/Config.h | 67 + include/pbbam/DataSet.h | 835 ++ include/pbbam/DataSetTypes.h | 1211 ++ include/pbbam/DataSetXsd.h | 116 + include/pbbam/EntireFileQuery.h | 65 + include/pbbam/FaiIndex.h | 101 + include/pbbam/FastaCache.h | 60 + include/pbbam/FastaReader.h | 85 + include/pbbam/FastaSequence.h | 82 + include/pbbam/FastaSequenceQuery.h | 52 + include/pbbam/FastaWriter.h | 47 + include/pbbam/FastqReader.h | 85 + include/pbbam/FastqSequence.h | 80 + include/pbbam/FastqWriter.h | 48 + include/pbbam/FormatUtils.h | 44 + include/pbbam/FrameEncodingType.h | 33 + include/pbbam/Frames.h | 26 + include/pbbam/GenomicInterval.h | 22 + include/pbbam/GenomicIntervalQuery.h | 103 + include/pbbam/IFastaWriter.h | 39 + include/pbbam/IFastqWriter.h | 43 + include/pbbam/IRecordWriter.h | 57 + include/pbbam/IndexedBamWriter.h | 155 + include/pbbam/IndexedFastaReader.h | 147 + include/pbbam/IndexedFastqReader.h | 141 + include/pbbam/Interval.h | 22 + include/pbbam/LocalContextFlags.h | 35 + include/pbbam/MD5.h | 24 + include/pbbam/MoveAppend.h | 52 + include/pbbam/Orientation.h | 22 + include/pbbam/PbiBasicTypes.h | 78 + include/pbbam/PbiBuilder.h | 179 + include/pbbam/PbiFile.h | 110 + include/pbbam/PbiFilter.h | 250 + include/pbbam/PbiFilterQuery.h | 80 + include/pbbam/PbiFilterTypes.h | 929 ++ include/pbbam/PbiIndexedBamReader.h | 124 + include/pbbam/PbiRawData.h | 465 + include/pbbam/Position.h | 35 + include/pbbam/ProgramInfo.h | 178 + include/pbbam/PulseBehavior.h | 27 + include/pbbam/PulseExclusionReason.h | 30 + include/pbbam/QNameQuery.h | 60 + include/pbbam/QualityValue.h | 26 + include/pbbam/QualityValues.h | 28 + include/pbbam/ReadAccuracyQuery.h | 69 + include/pbbam/ReadGroupInfo.h | 713 + include/pbbam/RecordType.h | 56 + include/pbbam/SNR.h | 27 + include/pbbam/SamTagCodec.h | 68 + include/pbbam/SamWriter.h | 96 + include/pbbam/SequenceInfo.h | 188 + include/pbbam/Strand.h | 22 + include/pbbam/StringUtilities.h | 44 + include/pbbam/SubreadLengthQuery.h | 67 + include/pbbam/Tag.h | 413 + include/pbbam/TagCollection.h | 35 + include/pbbam/TextFileReader.h | 87 + include/pbbam/TextFileWriter.h | 60 + include/pbbam/Unused.h | 15 + include/pbbam/Validator.h | 155 + include/pbbam/ZmwChunkedFastaReader.h | 100 + include/pbbam/ZmwChunkedFastqReader.h | 102 + include/pbbam/ZmwGroupQuery.h | 62 + include/pbbam/ZmwQuery.h | 62 + include/pbbam/ZmwType.h | 28 + include/pbbam/ZmwTypeMap.h | 31 + include/pbbam/bed/BedReader.h | 86 + include/pbbam/bed/BedWriter.h | 42 + include/pbbam/ccs/CCSHeader.h | 25 + include/pbbam/ccs/CCSPbiBuilder.h | 54 + include/pbbam/ccs/CCSRecord.h | 40 + include/pbbam/ccs/CCSRecordFormat.h | 29 + include/pbbam/ccs/CCSRecordReader.h | 42 + include/pbbam/ccs/CCSRecordWriter.h | 50 + .../BundleChemistryMappingException.h | 45 + .../InvalidSequencingChemistryException.h | 63 + include/pbbam/exception/ValidationException.h | 60 + include/pbbam/internal/Compare.inl | 43 + include/pbbam/internal/CompositeBamReader.inl | 360 + include/pbbam/internal/DataSetBaseTypes.h | 149 + include/pbbam/internal/DataSetElement.h | 202 + include/pbbam/internal/DataSetElement.inl | 411 + include/pbbam/internal/PbiBasicTypes.inl | 28 + include/pbbam/internal/PbiFilter.inl | 227 + include/pbbam/internal/PbiFilterTypes.inl | 508 + include/pbbam/internal/QueryBase.h | 107 + include/pbbam/internal/QueryBase.inl | 122 + include/pbbam/vcf/VcfFile.h | 32 + include/pbbam/vcf/VcfFormat.h | 107 + include/pbbam/vcf/VcfHeader.h | 115 + include/pbbam/vcf/VcfHeaderTypes.h | 126 + include/pbbam/vcf/VcfQuery.h | 40 + include/pbbam/vcf/VcfReader.h | 46 + include/pbbam/vcf/VcfSort.h | 32 + include/pbbam/vcf/VcfVariant.h | 146 + include/pbbam/vcf/VcfWriter.h | 37 + .../virtual/VirtualPolymeraseBamRecord.h | 23 + .../VirtualPolymeraseCompositeReader.h | 23 + .../pbbam/virtual/VirtualPolymeraseReader.h | 23 + include/pbbam/virtual/VirtualRegion.h | 50 + include/pbbam/virtual/VirtualRegionType.h | 30 + include/pbbam/virtual/VirtualRegionTypeMap.h | 31 + include/pbbam/virtual/VirtualZmwBamRecord.h | 78 + .../virtual/WhitelistedZmwReadStitcher.h | 103 + include/pbbam/virtual/ZmwReadStitcher.h | 89 + .../pbbam/virtual/ZmwWhitelistVirtualReader.h | 23 + meson.build | 140 + meson_options.txt | 24 + scripts/ci/artifact.sh | 65 + scripts/ci/build.sh | 66 + scripts/ci/install.sh | 21 + scripts/ci/setup.sh | 68 + scripts/ci/test.sh | 25 + src/AlignmentPrinter.cpp | 131 + src/Autovalidate.h | 24 + src/BaiIndexCache.cpp | 73 + src/BaiIndexedBamReader.cpp | 141 + src/BamFile.cpp | 194 + src/BamFileMerger.cpp | 260 + src/BamHeader.cpp | 453 + src/BamReader.cpp | 115 + src/BamRecord.cpp | 2006 +++ src/BamRecordBuilder.cpp | 396 + src/BamRecordImpl.cpp | 820 ++ src/BamRecordTags.cpp | 66 + src/BamRecordTags.h | 56 + src/BamRecordView.cpp | 138 + src/BamTagCodec.cpp | 546 + src/BamWriter.cpp | 166 + src/BarcodeQuery.cpp | 40 + src/BgzipFastaWriter.cpp | 53 + src/BgzipFastqWriter.cpp | 73 + src/BgzipWriter.cpp | 95 + src/ChemistryTable.cpp | 179 + src/ChemistryTable.h | 24 + src/Compare.cpp | 110 + src/CompositeFastaReader.cpp | 42 + src/Config.cpp | 58 + src/DataSet.cpp | 620 + src/DataSetBaseTypes.cpp | 322 + src/DataSetElement.cpp | 20 + src/DataSetIO.cpp | 156 + src/DataSetIO.h | 36 + src/DataSetTypes.cpp | 1176 ++ src/DataSetUtils.h | 73 + src/DataSetXsd.cpp | 226 + src/EntireFileQuery.cpp | 34 + src/FaiIndex.cpp | 139 + src/FaiZmwChunker.cpp | 119 + src/FaiZmwChunker.h | 84 + src/FastaCache.cpp | 61 + src/FastaReader.cpp | 79 + src/FastaSequence.cpp | 61 + src/FastaSequenceQuery.cpp | 34 + src/FastaWriter.cpp | 45 + src/FastqReader.cpp | 76 + src/FastqSequence.cpp | 55 + src/FastqWriter.cpp | 70 + src/FileProducer.cpp | 43 + src/FileProducer.h | 56 + src/FileUtils.cpp | 203 + src/FileUtils.h | 108 + src/FofnReader.cpp | 22 + src/FofnReader.h | 26 + src/FormatUtils.cpp | 61 + src/GenomicIntervalQuery.cpp | 70 + src/IFastaWriter.cpp | 19 + src/IFastqWriter.cpp | 19 + src/IRecordWriter.cpp | 19 + src/IndexedBamWriter.cpp | 1032 ++ src/IndexedFastaReader.cpp | 208 + src/IndexedFastqBgzfReader.cpp | 141 + src/IndexedFastqBgzfReader.h | 52 + src/IndexedFastqReader.cpp | 198 + src/IndexedFastqReaderImpl.cpp | 24 + src/IndexedFastqReaderImpl.h | 43 + src/IndexedFastqTextReader.cpp | 142 + src/IndexedFastqTextReader.h | 59 + src/KSeqReader.cpp | 54 + src/KSeqReader.h | 59 + src/MD5.cpp | 54 + src/MemoryUtils.cpp | 40 + src/MemoryUtils.h | 151 + src/PbbamInternalConfig.h | 18 + src/PbiBuilder.cpp | 662 + src/PbiFile.cpp | 37 + src/PbiFilter.cpp | 497 + src/PbiFilterQuery.cpp | 58 + src/PbiFilterTypes.cpp | 522 + src/PbiIndexIO.cpp | 401 + src/PbiIndexIO.h | 115 + src/PbiIndexedBamReader.cpp | 183 + src/PbiRawData.cpp | 352 + src/ProgramInfo.cpp | 157 + src/Pulse2BaseCache.h | 117 + src/QNameQuery.cpp | 74 + src/ReadAccuracyQuery.cpp | 43 + src/ReadGroupInfo.cpp | 920 ++ src/RecordType.cpp | 45 + src/SamTagCodec.cpp | 281 + src/SamWriter.cpp | 116 + src/SequenceInfo.cpp | 180 + src/SequenceUtils.h | 126 + src/StringUtilities.cpp | 48 + src/SubreadLengthQuery.cpp | 45 + src/Tag.cpp | 401 + src/TagCollection.cpp | 17 + src/TextFileReader.cpp | 115 + src/TextFileWriter.cpp | 88 + src/TimeUtils.h | 73 + src/ValidationErrors.cpp | 74 + src/ValidationErrors.h | 65 + src/ValidationException.cpp | 74 + src/Validator.cpp | 406 + src/Version.cpp | 51 + src/Version.h | 134 + src/VirtualRegion.cpp | 53 + src/VirtualRegionTypeMap.cpp | 22 + src/VirtualStitching.h | 70 + src/VirtualZmwBamRecord.cpp | 297 + src/VirtualZmwCompositeReader.cpp | 73 + src/VirtualZmwCompositeReader.h | 79 + src/VirtualZmwReader.cpp | 108 + src/VirtualZmwReader.h | 90 + src/WhitelistedZmwReadStitcher.cpp | 139 + src/XmlReader.cpp | 236 + src/XmlReader.h | 25 + src/XmlWriter.cpp | 167 + src/XmlWriter.h | 26 + src/ZmwChunkedFastaReader.cpp | 146 + src/ZmwChunkedFastqReader.cpp | 146 + src/ZmwChunkedFastxBgzfReader.cpp | 157 + src/ZmwChunkedFastxBgzfReader.h | 53 + src/ZmwChunkedFastxReaderImpl.cpp | 25 + src/ZmwChunkedFastxReaderImpl.h | 45 + src/ZmwChunkedFastxTextReader.cpp | 157 + src/ZmwChunkedFastxTextReader.h | 59 + src/ZmwGroupQuery.cpp | 78 + src/ZmwQuery.cpp | 40 + src/ZmwReadStitcher.cpp | 139 + src/ZmwTypeMap.cpp | 25 + src/bed/BedReader.cpp | 117 + src/bed/BedWriter.cpp | 55 + src/ccs/CCSPbiBuilder.cpp | 330 + src/ccs/CCSRecordFormat.cpp | 144 + src/ccs/CCSRecordReader.cpp | 65 + src/ccs/CCSRecordWriter.cpp | 56 + src/meson.build | 153 + src/pugixml/pugiconfig.hpp | 71 + src/pugixml/pugixml.cpp | 11539 ++++++++++++++++ src/pugixml/pugixml.hpp | 1366 ++ src/vcf/VcfFile.cpp | 34 + src/vcf/VcfFormat.cpp | 551 + src/vcf/VcfHeader.cpp | 234 + src/vcf/VcfHeaderTypes.cpp | 233 + src/vcf/VcfQuery.cpp | 33 + src/vcf/VcfReader.cpp | 55 + src/vcf/VcfSort.cpp | 58 + src/vcf/VcfVariant.cpp | 258 + src/vcf/VcfWriter.cpp | 56 + subprojects/gtest.wrap | 10 + subprojects/htslib.wrap | 10 + subprojects/pbcopper.wrap | 4 + subprojects/zlib.wrap | 10 + tests/data/aligned.bam | Bin 0 -> 786 bytes tests/data/aligned.bam.bai | Bin 0 -> 96 bytes tests/data/aligned.bam.pbi | Bin 0 -> 168 bytes tests/data/aligned.sam | 8 + tests/data/aligned2.bam | Bin 0 -> 22511 bytes tests/data/aligned2.bam.bai | Bin 0 -> 96 bytes tests/data/aligned2.bam.pbi | Bin 0 -> 366 bytes tests/data/barcoded_read_groups.bam | Bin 0 -> 498 bytes tests/data/barcoded_read_groups.bam.pbi | Bin 0 -> 126 bytes tests/data/bed/test.bed | 9 + tests/data/bed/test.bed.gz | Bin 0 -> 119 bytes tests/data/chemistry.xml | 9 + tests/data/chimera_minimal.fasta | 220 + tests/data/chunking/chunking.subreadset.xml | 32 + ...000001823174110291514_s1_p0.1.subreads.bam | Bin 0 -> 1088277 bytes ...01823174110291514_s1_p0.1.subreads.bam.pbi | Bin 0 -> 4293 bytes ...000001823174110291514_s1_p0.2.subreads.bam | Bin 0 -> 977970 bytes ...01823174110291514_s1_p0.2.subreads.bam.pbi | Bin 0 -> 4058 bytes ...000001823174110291514_s1_p0.3.subreads.bam | Bin 0 -> 971423 bytes ...01823174110291514_s1_p0.3.subreads.bam.pbi | Bin 0 -> 3821 bytes tests/data/clip_to_query.bam | Bin 0 -> 511 bytes tests/data/dataset/ali1.xml | 35 + tests/data/dataset/ali2.xml | 35 + tests/data/dataset/ali3.xml | 35 + tests/data/dataset/ali4.xml | 35 + tests/data/dataset/bam_mapping.bam | Bin 0 -> 169668 bytes tests/data/dataset/bam_mapping.bam.pbi | Bin 0 -> 2469 bytes tests/data/dataset/bam_mapping_1.bam | Bin 0 -> 167530 bytes tests/data/dataset/bam_mapping_1.bam.pbi | Bin 0 -> 2448 bytes tests/data/dataset/bam_mapping_2.bam | Bin 0 -> 165778 bytes tests/data/dataset/bam_mapping_2.bam.pbi | Bin 0 -> 2435 bytes tests/data/dataset/bam_mapping_new.bam | Bin 0 -> 22428 bytes tests/data/dataset/bam_mapping_new.bam.pbi | Bin 0 -> 362 bytes tests/data/dataset/bam_mapping_staggered.xml | 35 + tests/data/dataset/barcode.dataset.xml | 11 + tests/data/dataset/biosample.subreadset.xml | 748 + tests/data/dataset/ccsread.dataset.xml | 15 + tests/data/dataset/lambda_contigs.xml | 6 + tests/data/dataset/malformed.xml | 85 + tests/data/dataset/pbalchemy10kbp.xml | 17 + tests/data/dataset/qname_filter.bam | Bin 0 -> 390 bytes tests/data/dataset/qname_filter.bam.pbi | Bin 0 -> 114 bytes tests/data/dataset/reference.dataset.xml | 20 + tests/data/dataset/subread_dataset1.xml | 76 + tests/data/dataset/subread_dataset2.xml | 76 + tests/data/dataset/subread_dataset3.xml | 76 + .../transformed_rs_subread_dataset.xml | 75 + tests/data/empty.bam | Bin 0 -> 350 bytes tests/data/empty.bam.pbi | Bin 0 -> 67 bytes tests/data/fastx/chunking.fa | 70 + tests/data/fastx/chunking.fa.fai | 35 + tests/data/fastx/chunking.fq | 140 + tests/data/fastx/chunking.fq.fai | 35 + tests/data/fastx/simple-bgzf.fa.gz | Bin 0 -> 104 bytes tests/data/fastx/simple-bgzf.fa.gz.fai | 8 + tests/data/fastx/simple-bgzf.fa.gz.gzi | Bin 0 -> 8 bytes tests/data/fastx/simple-bgzf.fq.gz | Bin 0 -> 324 bytes tests/data/fastx/simple-bgzf.fq.gz.fai | 8 + tests/data/fastx/simple-bgzf.fq.gz.gzi | Bin 0 -> 8 bytes tests/data/fastx/simple-gzip.fa.gz | Bin 0 -> 83 bytes tests/data/fastx/simple-gzip.fq.gz | Bin 0 -> 298 bytes tests/data/fastx/simple.fa | 16 + tests/data/fastx/simple.fa.fai | 8 + tests/data/fastx/simple.fq | 32 + tests/data/fastx/simple.fq.fai | 8 + tests/data/fastx/windows_formatted.fasta | 14 + tests/data/fastx/windows_formatted.fastq | 4 + tests/data/group/group.fofn.in | 3 + tests/data/group/test1.bam | Bin 0 -> 2186 bytes tests/data/group/test2.bam | Bin 0 -> 13025 bytes tests/data/group/test2.bam.pbi | Bin 0 -> 199 bytes tests/data/group/test3.bam | Bin 0 -> 19332 bytes tests/data/lambdaNEB.fa | 608 + tests/data/lambdaNEB.fa.fai | 1 + tests/data/long-cigar-1.7.bam | Bin 0 -> 191942 bytes tests/data/long_reads.bam | Bin 0 -> 2592334 bytes tests/data/merge.fofn | 2 + tests/data/pbbamify/input-aligned-1.bam | Bin 0 -> 571 bytes tests/data/pbbamify/input-aligned-2.bam | Bin 0 -> 510 bytes tests/data/pbbamify/input-aligned-3.bam | Bin 0 -> 267 bytes tests/data/pbbamify/input-aligned-all.bam | Bin 0 -> 725 bytes tests/data/pbbamify/synthetic-ref-1.fa | 2 + tests/data/pbbamify/synthetic-ref-1.fa.fai | 1 + .../pbbamify/synthetic_movie_1.subreads.bam | Bin 0 -> 815 bytes .../synthetic_movie_1.subreads.bam.bai | Bin 0 -> 16 bytes .../synthetic_movie_1.subreads.bam.pbi | Bin 0 -> 112 bytes .../pbbamify/synthetic_movie_2.subreads.bam | Bin 0 -> 832 bytes .../synthetic_movie_2.subreads.bam.bai | Bin 0 -> 16 bytes .../synthetic_movie_2.subreads.bam.pbi | Bin 0 -> 106 bytes .../pbbamify/synthetic_movie_3.subreads.bam | Bin 0 -> 533 bytes .../synthetic_movie_3.subreads.bam.bai | Bin 0 -> 16 bytes .../synthetic_movie_3.subreads.bam.pbi | Bin 0 -> 90 bytes .../synthetic_movie_all.subreadset.xml.in | 27 + tests/data/phi29.bam | Bin 0 -> 71653 bytes tests/data/phi29.bam.pbi | Bin 0 -> 1394 bytes .../consolidate.subread.dataset.xml | 38 + .../filtered_resources.subread.dataset.xml | 67 + tests/data/polymerase/internal.hqregions.bam | Bin 0 -> 84188 bytes .../polymerase/internal.hqregions.bam.pbi | Bin 0 -> 95 bytes tests/data/polymerase/internal.lqregions.bam | Bin 0 -> 53115 bytes .../polymerase/internal.lqregions.bam.pbi | Bin 0 -> 110 bytes tests/data/polymerase/internal.polymerase.bam | Bin 0 -> 400570 bytes .../polymerase/internal.polymerase.bam.pbi | Bin 0 -> 116 bytes tests/data/polymerase/internal.scraps.bam | Bin 0 -> 203276 bytes tests/data/polymerase/internal.scraps.bam.pbi | Bin 0 -> 447 bytes tests/data/polymerase/internal.subreads.bam | Bin 0 -> 218924 bytes .../data/polymerase/internal.subreads.bam.pbi | Bin 0 -> 281 bytes .../multiple_resources.subread.dataset.xml | 46 + .../data/polymerase/production.polymerase.bam | Bin 0 -> 25082 bytes tests/data/polymerase/production.scraps.bam | Bin 0 -> 13535 bytes .../data/polymerase/production.scraps.bam.pbi | Bin 0 -> 284 bytes tests/data/polymerase/production.subreads.bam | Bin 0 -> 14659 bytes .../polymerase/production.subreads.bam.pbi | Bin 0 -> 188 bytes .../polymerase/production_hq.hqregion.bam | Bin 0 -> 15803 bytes .../polymerase/production_hq.hqregion.bam.pbi | Bin 0 -> 91 bytes .../data/polymerase/production_hq.scraps.bam | Bin 0 -> 10070 bytes .../polymerase/production_hq.scraps.bam.pbi | Bin 0 -> 104 bytes .../qnameFiltered.subreads.dataset.xml | 37 + tests/data/polymerase/qname_whitelist.txt | 3 + tests/data/polymerase/scrapless.scraps.bam | Bin 0 -> 436 bytes .../data/polymerase/scrapless.scraps.bam.pbi | Bin 0 -> 65 bytes tests/data/polymerase/scrapless.subreads.bam | Bin 0 -> 33466 bytes .../polymerase/scrapless.subreads.bam.pbi | Bin 0 -> 114 bytes tests/data/referenceset.xml | 21 + tests/data/refskip.bam | Bin 0 -> 186891 bytes tests/data/relative/a/test.bam | Bin 0 -> 462 bytes tests/data/relative/b/test1.bam | Bin 0 -> 462 bytes tests/data/relative/b/test2.bam | Bin 0 -> 462 bytes tests/data/relative/relative.fofn | 3 + tests/data/relative/relative.xml | 8 + tests/data/relative/relative2.fofn | 4 + tests/data/segfault.bam | Bin 0 -> 425 bytes tests/data/softclip_deletions.bam | Bin 0 -> 2240 bytes tests/data/stitching/test_qstart.scraps.bam | Bin 0 -> 962 bytes .../data/stitching/test_qstart.scraps.bam.pbi | Bin 0 -> 118 bytes tests/data/stitching/test_qstart.subreads.bam | Bin 0 -> 3600 bytes .../stitching/test_qstart.subreads.bam.pbi | Bin 0 -> 131 bytes .../adjacent_intervals.alignmentset.xml | 31 + .../contig_name_only.alignmentset.xml | 22 + .../disjoint_intervals.alignmentset.xml | 31 + .../empty.alignmentset.xml | 24 + .../invalid_missing_rname.alignmentset.xml | 23 + .../invalid_rname_operator.alignmentset.xml | 24 + .../invalid_tstart_operator.alignmentset.xml | 24 + .../no_filter.alignmentset.xml | 15 + .../out_of_range.alignmentset.xml | 24 + .../single_interval.alignmentset.xml | 24 + .../single_interval_end_gte.alignmentset.xml | 24 + ...single_interval_start_lte.alignmentset.xml | 24 + .../test_GenomicIntervals/test_contigs.bam | Bin 0 -> 282 bytes .../test_contigs.bam.pbi | Bin 0 -> 79 bytes .../test_GenomicIntervals/test_contigs.fasta | 4 + .../two_contigs.alignmentset.xml | 31 + .../whole_contig.alignmentset.xml | 24 + tests/data/test_group_query/group.fofn.in | 3 + tests/data/test_group_query/test1.bam | Bin 0 -> 2168 bytes tests/data/test_group_query/test2.bam | Bin 0 -> 13008 bytes tests/data/test_group_query/test2.bam.pbi | Bin 0 -> 197 bytes tests/data/test_group_query/test3.bam | Bin 0 -> 19294 bytes tests/data/transcript.subreads.bam | Bin 0 -> 330 bytes tests/data/transcript.subreads.bam.pbi | Bin 0 -> 107 bytes tests/data/transcriptset.xml | 21 + tests/data/unmap1.bam | Bin 0 -> 484 bytes tests/data/unmap1.bam.bai | Bin 0 -> 72 bytes tests/data/unmap2.bam | Bin 0 -> 1344 bytes tests/data/unmap2.bam.bai | Bin 0 -> 144 bytes tests/data/vcf/structural_variants.vcf | 32 + tests/data/vcf/unsorted.vcf | 12 + tests/meson.build | 70 + tests/scripts/generate_data.py | 188 + tests/src/FastxTests.h | 92 + tests/src/PbbamTestData.h.in | 23 + tests/src/cram/bam2sam.t.in | 47 + tests/src/cram/pbbamify.t.in | 147 + tests/src/cram/pbindexdump_cpp.t.in | 34 + tests/src/cram/pbindexdump_json.t.in | 83 + tests/src/cram/pbmerge_aligned_ordering.t.in | 197 + tests/src/cram/pbmerge_dataset.t.in | 144 + tests/src/cram/pbmerge_fofn.t.in | 120 + tests/src/cram/pbmerge_mixed_ordering.t.in | 57 + tests/src/cram/pbmerge_pacbio_ordering.t.in | 457 + tests/src/meson.build | 86 + tests/src/test_AlignmentPrinter.cpp | 120 + tests/src/test_BamFile.cpp | 105 + tests/src/test_BamHeader.cpp | 392 + tests/src/test_BamRecord.cpp | 2761 ++++ tests/src/test_BamRecordBuilder.cpp | 174 + tests/src/test_BamRecordClipping.cpp | 2401 ++++ tests/src/test_BamRecordImplCore.cpp | 597 + tests/src/test_BamRecordImplTags.cpp | 179 + tests/src/test_BamRecordImplVariableData.cpp | 4526 ++++++ tests/src/test_BamRecordMapping.cpp | 702 + tests/src/test_BamWriter.cpp | 113 + tests/src/test_BarcodeQuery.cpp | 17 + tests/src/test_BedReader.cpp | 125 + tests/src/test_BedWriter.cpp | 72 + tests/src/test_BgzipFastaWriter.cpp | 39 + tests/src/test_BgzipFastqWriter.cpp | 38 + tests/src/test_BgzipWriter.cpp | 26 + tests/src/test_CCSPbiBuilder.cpp | 77 + tests/src/test_CCSRecordIO.cpp | 236 + tests/src/test_Cigar.cpp | 165 + tests/src/test_Compare.cpp | 715 + tests/src/test_DataSetCore.cpp | 569 + tests/src/test_DataSetIO.cpp | 1754 +++ tests/src/test_DataSetQuery.cpp | 463 + tests/src/test_DataSetXsd.cpp | 140 + tests/src/test_EndToEnd.cpp | 206 + tests/src/test_EntireFileQuery.cpp | 106 + tests/src/test_FaiIndex.cpp | 111 + tests/src/test_FaiZmwChunker.cpp | 101 + tests/src/test_FastaReader.cpp | 195 + tests/src/test_FastaSequence.cpp | 31 + tests/src/test_FastaSequenceQuery.cpp | 66 + tests/src/test_FastaWriter.cpp | 106 + tests/src/test_FastqReader.cpp | 232 + tests/src/test_FastqSequence.cpp | 35 + tests/src/test_FastqWriter.cpp | 100 + tests/src/test_FileUtils.cpp | 287 + tests/src/test_Frames.cpp | 46 + tests/src/test_GenomicIntervalQuery.cpp | 205 + tests/src/test_GenomicIntervals.cpp | 165 + tests/src/test_IndexedBamWriter.cpp | 125 + tests/src/test_IndexedFastaReader.cpp | 169 + tests/src/test_IndexedFastqReader.cpp | 137 + tests/src/test_LongCigar.cpp | 125 + tests/src/test_PacBioIndex.cpp | 444 + tests/src/test_PbiFilter.cpp | 1364 ++ tests/src/test_PbiFilterQuery.cpp | 919 ++ tests/src/test_Pulse2BaseCache.cpp | 47 + tests/src/test_QNameQuery.cpp | 64 + tests/src/test_QualityValues.cpp | 88 + tests/src/test_ReadAccuracyQuery.cpp | 42 + tests/src/test_ReadGroupInfo.cpp | 317 + tests/src/test_SamWriter.cpp | 170 + tests/src/test_SequenceUtils.cpp | 80 + tests/src/test_StringUtils.cpp | 81 + tests/src/test_SubreadLengthQuery.cpp | 54 + tests/src/test_Tags.cpp | 1115 ++ tests/src/test_TextFileReader.cpp | 140 + tests/src/test_TextFileWriter.cpp | 61 + tests/src/test_TimeUtils.cpp | 32 + tests/src/test_Validator.cpp | 571 + tests/src/test_VcfFile.cpp | 44 + tests/src/test_VcfFormat.cpp | 421 + tests/src/test_VcfHeader.cpp | 189 + tests/src/test_VcfQuery.cpp | 49 + tests/src/test_VcfReader.cpp | 51 + tests/src/test_VcfSort.cpp | 51 + tests/src/test_VcfVariant.cpp | 234 + tests/src/test_VcfWriter.cpp | 55 + tests/src/test_Version.cpp | 294 + tests/src/test_WhitelistedZmwReadStitcher.cpp | 220 + tests/src/test_ZmwChunkedFastxReader.cpp | 121 + tests/src/test_ZmwQuery.cpp | 31 + tests/src/test_ZmwReadStitcher.cpp | 486 + tools/bam2sam/src/Bam2SamSettings.cpp | 81 + tools/bam2sam/src/Bam2SamSettings.h | 27 + tools/bam2sam/src/Bam2SamVersion.h.in | 16 + tools/bam2sam/src/Bam2SamWorkflow.cpp | 88 + tools/bam2sam/src/Bam2SamWorkflow.h | 19 + tools/bam2sam/src/main.cpp | 21 + tools/check-formatting | 34 + tools/format-all | 9 + tools/git-clang-format | 485 + tools/meson.build | 239 + tools/pbbamify/src/PbBamifySettings.cpp | 120 + tools/pbbamify/src/PbBamifySettings.h | 32 + tools/pbbamify/src/PbBamifyVersion.h.in | 16 + tools/pbbamify/src/PbBamifyWorkflow.cpp | 404 + tools/pbbamify/src/PbBamifyWorkflow.h | 125 + tools/pbbamify/src/QueryLookup.cpp | 104 + tools/pbbamify/src/QueryLookup.h | 66 + tools/pbbamify/src/main.cpp | 21 + tools/pbindex/src/PbIndexSettings.cpp | 49 + tools/pbindex/src/PbIndexSettings.h | 25 + tools/pbindex/src/PbIndexVersion.h.in | 16 + tools/pbindex/src/PbIndexWorkflow.cpp | 21 + tools/pbindex/src/PbIndexWorkflow.h | 19 + tools/pbindex/src/main.cpp | 21 + tools/pbindexdump/src/CppFormatter.cpp | 145 + tools/pbindexdump/src/CppFormatter.h | 19 + tools/pbindexdump/src/JsonFormatter.cpp | 171 + tools/pbindexdump/src/JsonFormatter.h | 19 + tools/pbindexdump/src/PbIndexDumpSettings.cpp | 113 + tools/pbindexdump/src/PbIndexDumpSettings.h | 28 + tools/pbindexdump/src/PbIndexDumpVersion.h.in | 16 + tools/pbindexdump/src/PbIndexDumpWorkflow.cpp | 28 + tools/pbindexdump/src/PbIndexDumpWorkflow.h | 19 + tools/pbindexdump/src/main.cpp | 21 + tools/pbmerge/src/PbMergeSettings.cpp | 84 + tools/pbmerge/src/PbMergeSettings.h | 29 + tools/pbmerge/src/PbMergeVersion.h.in | 16 + tools/pbmerge/src/PbMergeWorkflow.cpp | 37 + tools/pbmerge/src/PbMergeWorkflow.h | 22 + tools/pbmerge/src/main.cpp | 21 + 778 files changed, 96697 insertions(+) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 INSTALL.md create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100755 bamboo_build.sh create mode 100644 docs/Doxyfile.in create mode 100644 docs/Makefile create mode 100644 docs/examples/code/BarcodeQuery.txt create mode 100644 docs/examples/code/Compare.txt create mode 100644 docs/examples/code/Compare_AlignedEnd.txt create mode 100644 docs/examples/code/Compare_AlignedStart.txt create mode 100644 docs/examples/code/Compare_AlignedStrand.txt create mode 100644 docs/examples/code/Compare_BarcodeForward.txt create mode 100644 docs/examples/code/Compare_BarcodeQuality.txt create mode 100644 docs/examples/code/Compare_BarcodeReverse.txt create mode 100644 docs/examples/code/Compare_FullName.txt create mode 100644 docs/examples/code/Compare_LocalContextFlag.txt create mode 100644 docs/examples/code/Compare_MapQuality.txt create mode 100644 docs/examples/code/Compare_MovieName.txt create mode 100644 docs/examples/code/Compare_NumDeletedBases.txt create mode 100644 docs/examples/code/Compare_NumInsertedBases.txt create mode 100644 docs/examples/code/Compare_NumMatches.txt create mode 100644 docs/examples/code/Compare_NumMismatches.txt create mode 100644 docs/examples/code/Compare_QueryEnd.txt create mode 100644 docs/examples/code/Compare_QueryStart.txt create mode 100644 docs/examples/code/Compare_ReadAccuracy.txt create mode 100644 docs/examples/code/Compare_ReadGroupId.txt create mode 100644 docs/examples/code/Compare_ReadGroupNumericId.txt create mode 100644 docs/examples/code/Compare_ReferenceEnd.txt create mode 100644 docs/examples/code/Compare_ReferenceId.txt create mode 100644 docs/examples/code/Compare_ReferenceName.txt create mode 100644 docs/examples/code/Compare_ReferenceStart.txt create mode 100644 docs/examples/code/Compare_TypeFromOperator.txt create mode 100644 docs/examples/code/Compare_TypeToName.txt create mode 100644 docs/examples/code/Compare_Zmw.txt create mode 100644 docs/examples/code/EntireFileQuery.txt create mode 100644 docs/examples/code/EntireFileQuery_BamFilename.txt create mode 100644 docs/examples/code/EntireFileQuery_NonConst.txt create mode 100644 docs/examples/code/GenomicIntervalQuery.txt create mode 100644 docs/examples/code/GenomicIntervalQuery_Reuse.txt create mode 100644 docs/examples/code/PbiAlignedEndFilter.txt create mode 100644 docs/examples/code/PbiAlignedLengthFilter.txt create mode 100644 docs/examples/code/PbiAlignedStartFilter.txt create mode 100644 docs/examples/code/PbiAlignedStrandFilter.txt create mode 100644 docs/examples/code/PbiBarcodeFilter.txt create mode 100644 docs/examples/code/PbiBarcodeForwardFilter.txt create mode 100644 docs/examples/code/PbiBarcodeQualityFilter.txt create mode 100644 docs/examples/code/PbiBarcodeReverseFilter.txt create mode 100644 docs/examples/code/PbiBarcodesFilter.txt create mode 100644 docs/examples/code/PbiBuilder_WithReader.txt create mode 100644 docs/examples/code/PbiBuilder_WithWriter.txt create mode 100644 docs/examples/code/PbiFilterQuery.txt create mode 100644 docs/examples/code/PbiFilter_Composition.txt create mode 100644 docs/examples/code/PbiFilter_CustomFilter.txt create mode 100644 docs/examples/code/PbiFilter_Interface.txt create mode 100644 docs/examples/code/PbiIdentityFilter.txt create mode 100644 docs/examples/code/PbiLocalContextFilter.txt create mode 100644 docs/examples/code/PbiMapQualityFilter.txt create mode 100644 docs/examples/code/PbiMovieNameFilter.txt create mode 100644 docs/examples/code/PbiNumDeletedBasesFilter.txt create mode 100644 docs/examples/code/PbiNumInsertedBasesFilter.txt create mode 100644 docs/examples/code/PbiNumMatchesFilter.txt create mode 100644 docs/examples/code/PbiNumMismatchesFilter.txt create mode 100644 docs/examples/code/PbiQueryEndFilter.txt create mode 100644 docs/examples/code/PbiQueryLengthFilter.txt create mode 100644 docs/examples/code/PbiQueryNameFilter.txt create mode 100644 docs/examples/code/PbiQueryStartFilter.txt create mode 100644 docs/examples/code/PbiReadAccuracyFilter.txt create mode 100644 docs/examples/code/PbiReadGroupFilter.txt create mode 100644 docs/examples/code/PbiReferenceEndFilter.txt create mode 100644 docs/examples/code/PbiReferenceIdFilter.txt create mode 100644 docs/examples/code/PbiReferenceNameFilter.txt create mode 100644 docs/examples/code/PbiReferenceStartFilter.txt create mode 100644 docs/examples/code/PbiZmwFilter.txt create mode 100644 docs/examples/code/ReadAccuracyQuery.txt create mode 100644 docs/examples/code/SubreadLengthQuery.txt create mode 100644 docs/examples/code/Tag_AsciiCtor.txt create mode 100644 docs/examples/code/WhitelistedZmwReadStitcher.txt create mode 100644 docs/examples/code/ZmwGroupQuery.txt create mode 100644 docs/examples/code/ZmwQuery.txt create mode 100644 docs/examples/plaintext/AlignmentPrinterOutput.txt create mode 100644 docs/examples/plaintext/PbiFilter_DataSetXmlFilters.txt create mode 100644 docs/meson.build create mode 100644 docs/source/api/Accuracy.rst create mode 100644 docs/source/api/AlignmentPrinter.rst create mode 100644 docs/source/api/AlignmentSet.rst create mode 100644 docs/source/api/BaiIndexedBamReader.rst create mode 100644 docs/source/api/BamFile.rst create mode 100644 docs/source/api/BamHeader.rst create mode 100644 docs/source/api/BamReader.rst create mode 100644 docs/source/api/BamRecord.rst create mode 100644 docs/source/api/BamRecordBuilder.rst create mode 100644 docs/source/api/BamRecordImpl.rst create mode 100644 docs/source/api/BamRecordView.rst create mode 100644 docs/source/api/BamTagCodec.rst create mode 100644 docs/source/api/BamWriter.rst create mode 100644 docs/source/api/BarcodeQuery.rst create mode 100644 docs/source/api/BarcodeSet.rst create mode 100644 docs/source/api/Cigar.rst create mode 100644 docs/source/api/CigarOperation.rst create mode 100644 docs/source/api/Compare.rst create mode 100644 docs/source/api/Config.rst create mode 100644 docs/source/api/ConsensusAlignmentSet.rst create mode 100644 docs/source/api/ConsensusReadSet.rst create mode 100644 docs/source/api/ContigSet.rst create mode 100644 docs/source/api/DataSet.rst create mode 100644 docs/source/api/DataSetBase.rst create mode 100644 docs/source/api/DataSetMetadata.rst create mode 100644 docs/source/api/EntireFileQuery.rst create mode 100644 docs/source/api/ExtensionElement.rst create mode 100644 docs/source/api/Extensions.rst create mode 100644 docs/source/api/ExternalResource.rst create mode 100644 docs/source/api/ExternalResources.rst create mode 100644 docs/source/api/FileIndex.rst create mode 100644 docs/source/api/FileIndices.rst create mode 100644 docs/source/api/Filter.rst create mode 100644 docs/source/api/Filters.rst create mode 100644 docs/source/api/Frames.rst create mode 100644 docs/source/api/GenomicInterval.rst create mode 100644 docs/source/api/GenomicIntervalCompositeBamReader.rst create mode 100644 docs/source/api/GenomicIntervalQuery.rst create mode 100644 docs/source/api/HdfSubreadSet.rst create mode 100644 docs/source/api/IndexResultBlock.rst create mode 100644 docs/source/api/IndexedFastaReader.rst create mode 100644 docs/source/api/Interval.rst create mode 100644 docs/source/api/InvalidSequencingChemistryException.rst create mode 100644 docs/source/api/LocalContextFlags.rst create mode 100644 docs/source/api/NamespaceInfo.rst create mode 100644 docs/source/api/NamespaceRegistry.rst create mode 100644 docs/source/api/Orientation.rst create mode 100644 docs/source/api/ParentTool.rst create mode 100644 docs/source/api/PbiBuilder.rst create mode 100644 docs/source/api/PbiFile.rst create mode 100644 docs/source/api/PbiFilter.rst create mode 100644 docs/source/api/PbiFilterCompositeBamReader.rst create mode 100644 docs/source/api/PbiFilterQuery.rst create mode 100644 docs/source/api/PbiFilterTypes.rst create mode 100644 docs/source/api/PbiIndexedBamReader.rst create mode 100644 docs/source/api/PbiRawBarcodeData.rst create mode 100644 docs/source/api/PbiRawBasicData.rst create mode 100644 docs/source/api/PbiRawData.rst create mode 100644 docs/source/api/PbiRawMappedData.rst create mode 100644 docs/source/api/PbiRawReferenceData.rst create mode 100644 docs/source/api/PbiReferenceEntry.rst create mode 100644 docs/source/api/Position.rst create mode 100644 docs/source/api/ProgramInfo.rst create mode 100644 docs/source/api/QNameQuery.rst create mode 100644 docs/source/api/QualityValue.rst create mode 100644 docs/source/api/QualityValues.rst create mode 100644 docs/source/api/ReadAccuracyQuery.rst create mode 100644 docs/source/api/ReadGroupInfo.rst create mode 100644 docs/source/api/ReferenceSet.rst create mode 100644 docs/source/api/SamTagCodec.rst create mode 100644 docs/source/api/SequenceInfo.rst create mode 100644 docs/source/api/SequentialCompositeBamReader.rst create mode 100644 docs/source/api/Strand.rst create mode 100644 docs/source/api/SubDataSets.rst create mode 100644 docs/source/api/SubreadLengthQuery.rst create mode 100644 docs/source/api/SubreadSet.rst create mode 100644 docs/source/api/Tag.rst create mode 100644 docs/source/api/TagCollection.rst create mode 100644 docs/source/api/VirtualPolymeraseBamRecord.rst create mode 100644 docs/source/api/VirtualPolymeraseCompositeReader.rst create mode 100644 docs/source/api/VirtualPolymeraseReader.rst create mode 100644 docs/source/api/VirtualRegion.rst create mode 100644 docs/source/api/VirtualRegionType.rst create mode 100644 docs/source/api/VirtualRegionTypeMap.rst create mode 100644 docs/source/api/ZmwGroupQuery.rst create mode 100644 docs/source/api/ZmwQuery.rst create mode 100644 docs/source/api/ZmwWhitelistVirtualReader.rst create mode 100644 docs/source/api_reference.rst create mode 100644 docs/source/commandline_utilities.rst create mode 100755 docs/source/conf.py create mode 100644 docs/source/getting_started.rst create mode 100644 docs/source/index.rst create mode 100644 docs/source/pacbio-theme/static/headerGradient.jpg create mode 100644 docs/source/pacbio-theme/static/pacbio.css create mode 100644 docs/source/pacbio-theme/static/pacbioLogo.png create mode 100644 docs/source/pacbio-theme/static/pygments.css create mode 100644 docs/source/pacbio-theme/theme.conf create mode 100644 docs/source/requirements.txt create mode 100644 docs/source/tools/bam2sam.rst create mode 100644 docs/source/tools/pbindex.rst create mode 100644 docs/source/tools/pbindexdump.rst create mode 100644 docs/source/tools/pbmerge.rst create mode 100644 docs/specs/pbbam.rst create mode 100755 docs/specs/pbbam_structure.png create mode 100755 docs/specs/pbbam_updated_release3_2.rst create mode 100644 include/meson.build create mode 100644 include/pbbam/Accuracy.h create mode 100644 include/pbbam/AlignmentPrinter.h create mode 100644 include/pbbam/BaiIndexCache.h create mode 100644 include/pbbam/BaiIndexedBamReader.h create mode 100644 include/pbbam/BamFile.h create mode 100644 include/pbbam/BamFileMerger.h create mode 100644 include/pbbam/BamHeader.h create mode 100644 include/pbbam/BamReader.h create mode 100644 include/pbbam/BamRecord.h create mode 100644 include/pbbam/BamRecordBuilder.h create mode 100644 include/pbbam/BamRecordImpl.h create mode 100644 include/pbbam/BamRecordTag.h create mode 100644 include/pbbam/BamRecordView.h create mode 100644 include/pbbam/BamTagCodec.h create mode 100644 include/pbbam/BamWriter.h create mode 100644 include/pbbam/BarcodeQuery.h create mode 100644 include/pbbam/BgzipFastaWriter.h create mode 100644 include/pbbam/BgzipFastqWriter.h create mode 100644 include/pbbam/BgzipWriter.h create mode 100644 include/pbbam/Cigar.h create mode 100644 include/pbbam/CigarOperation.h create mode 100644 include/pbbam/ClipType.h create mode 100644 include/pbbam/Compare.h create mode 100644 include/pbbam/CompositeBamReader.h create mode 100644 include/pbbam/CompositeFastaReader.h create mode 100644 include/pbbam/Config.h create mode 100644 include/pbbam/DataSet.h create mode 100644 include/pbbam/DataSetTypes.h create mode 100644 include/pbbam/DataSetXsd.h create mode 100644 include/pbbam/EntireFileQuery.h create mode 100644 include/pbbam/FaiIndex.h create mode 100644 include/pbbam/FastaCache.h create mode 100644 include/pbbam/FastaReader.h create mode 100644 include/pbbam/FastaSequence.h create mode 100644 include/pbbam/FastaSequenceQuery.h create mode 100644 include/pbbam/FastaWriter.h create mode 100644 include/pbbam/FastqReader.h create mode 100644 include/pbbam/FastqSequence.h create mode 100644 include/pbbam/FastqWriter.h create mode 100644 include/pbbam/FormatUtils.h create mode 100644 include/pbbam/FrameEncodingType.h create mode 100644 include/pbbam/Frames.h create mode 100644 include/pbbam/GenomicInterval.h create mode 100644 include/pbbam/GenomicIntervalQuery.h create mode 100644 include/pbbam/IFastaWriter.h create mode 100644 include/pbbam/IFastqWriter.h create mode 100644 include/pbbam/IRecordWriter.h create mode 100644 include/pbbam/IndexedBamWriter.h create mode 100644 include/pbbam/IndexedFastaReader.h create mode 100644 include/pbbam/IndexedFastqReader.h create mode 100644 include/pbbam/Interval.h create mode 100644 include/pbbam/LocalContextFlags.h create mode 100644 include/pbbam/MD5.h create mode 100644 include/pbbam/MoveAppend.h create mode 100644 include/pbbam/Orientation.h create mode 100644 include/pbbam/PbiBasicTypes.h create mode 100644 include/pbbam/PbiBuilder.h create mode 100644 include/pbbam/PbiFile.h create mode 100644 include/pbbam/PbiFilter.h create mode 100644 include/pbbam/PbiFilterQuery.h create mode 100644 include/pbbam/PbiFilterTypes.h create mode 100644 include/pbbam/PbiIndexedBamReader.h create mode 100644 include/pbbam/PbiRawData.h create mode 100644 include/pbbam/Position.h create mode 100644 include/pbbam/ProgramInfo.h create mode 100644 include/pbbam/PulseBehavior.h create mode 100644 include/pbbam/PulseExclusionReason.h create mode 100644 include/pbbam/QNameQuery.h create mode 100644 include/pbbam/QualityValue.h create mode 100644 include/pbbam/QualityValues.h create mode 100644 include/pbbam/ReadAccuracyQuery.h create mode 100644 include/pbbam/ReadGroupInfo.h create mode 100644 include/pbbam/RecordType.h create mode 100644 include/pbbam/SNR.h create mode 100644 include/pbbam/SamTagCodec.h create mode 100644 include/pbbam/SamWriter.h create mode 100644 include/pbbam/SequenceInfo.h create mode 100644 include/pbbam/Strand.h create mode 100644 include/pbbam/StringUtilities.h create mode 100644 include/pbbam/SubreadLengthQuery.h create mode 100644 include/pbbam/Tag.h create mode 100644 include/pbbam/TagCollection.h create mode 100644 include/pbbam/TextFileReader.h create mode 100644 include/pbbam/TextFileWriter.h create mode 100644 include/pbbam/Unused.h create mode 100644 include/pbbam/Validator.h create mode 100644 include/pbbam/ZmwChunkedFastaReader.h create mode 100644 include/pbbam/ZmwChunkedFastqReader.h create mode 100644 include/pbbam/ZmwGroupQuery.h create mode 100644 include/pbbam/ZmwQuery.h create mode 100644 include/pbbam/ZmwType.h create mode 100644 include/pbbam/ZmwTypeMap.h create mode 100644 include/pbbam/bed/BedReader.h create mode 100644 include/pbbam/bed/BedWriter.h create mode 100644 include/pbbam/ccs/CCSHeader.h create mode 100644 include/pbbam/ccs/CCSPbiBuilder.h create mode 100644 include/pbbam/ccs/CCSRecord.h create mode 100644 include/pbbam/ccs/CCSRecordFormat.h create mode 100644 include/pbbam/ccs/CCSRecordReader.h create mode 100644 include/pbbam/ccs/CCSRecordWriter.h create mode 100644 include/pbbam/exception/BundleChemistryMappingException.h create mode 100644 include/pbbam/exception/InvalidSequencingChemistryException.h create mode 100644 include/pbbam/exception/ValidationException.h create mode 100644 include/pbbam/internal/Compare.inl create mode 100644 include/pbbam/internal/CompositeBamReader.inl create mode 100644 include/pbbam/internal/DataSetBaseTypes.h create mode 100644 include/pbbam/internal/DataSetElement.h create mode 100644 include/pbbam/internal/DataSetElement.inl create mode 100644 include/pbbam/internal/PbiBasicTypes.inl create mode 100644 include/pbbam/internal/PbiFilter.inl create mode 100644 include/pbbam/internal/PbiFilterTypes.inl create mode 100644 include/pbbam/internal/QueryBase.h create mode 100644 include/pbbam/internal/QueryBase.inl create mode 100644 include/pbbam/vcf/VcfFile.h create mode 100644 include/pbbam/vcf/VcfFormat.h create mode 100644 include/pbbam/vcf/VcfHeader.h create mode 100644 include/pbbam/vcf/VcfHeaderTypes.h create mode 100644 include/pbbam/vcf/VcfQuery.h create mode 100644 include/pbbam/vcf/VcfReader.h create mode 100644 include/pbbam/vcf/VcfSort.h create mode 100644 include/pbbam/vcf/VcfVariant.h create mode 100644 include/pbbam/vcf/VcfWriter.h create mode 100644 include/pbbam/virtual/VirtualPolymeraseBamRecord.h create mode 100644 include/pbbam/virtual/VirtualPolymeraseCompositeReader.h create mode 100644 include/pbbam/virtual/VirtualPolymeraseReader.h create mode 100644 include/pbbam/virtual/VirtualRegion.h create mode 100644 include/pbbam/virtual/VirtualRegionType.h create mode 100644 include/pbbam/virtual/VirtualRegionTypeMap.h create mode 100644 include/pbbam/virtual/VirtualZmwBamRecord.h create mode 100644 include/pbbam/virtual/WhitelistedZmwReadStitcher.h create mode 100644 include/pbbam/virtual/ZmwReadStitcher.h create mode 100644 include/pbbam/virtual/ZmwWhitelistVirtualReader.h create mode 100644 meson.build create mode 100644 meson_options.txt create mode 100755 scripts/ci/artifact.sh create mode 100755 scripts/ci/build.sh create mode 100755 scripts/ci/install.sh create mode 100755 scripts/ci/setup.sh create mode 100755 scripts/ci/test.sh create mode 100644 src/AlignmentPrinter.cpp create mode 100644 src/Autovalidate.h create mode 100644 src/BaiIndexCache.cpp create mode 100644 src/BaiIndexedBamReader.cpp create mode 100644 src/BamFile.cpp create mode 100644 src/BamFileMerger.cpp create mode 100644 src/BamHeader.cpp create mode 100644 src/BamReader.cpp create mode 100644 src/BamRecord.cpp create mode 100644 src/BamRecordBuilder.cpp create mode 100644 src/BamRecordImpl.cpp create mode 100644 src/BamRecordTags.cpp create mode 100644 src/BamRecordTags.h create mode 100644 src/BamRecordView.cpp create mode 100644 src/BamTagCodec.cpp create mode 100644 src/BamWriter.cpp create mode 100644 src/BarcodeQuery.cpp create mode 100644 src/BgzipFastaWriter.cpp create mode 100644 src/BgzipFastqWriter.cpp create mode 100644 src/BgzipWriter.cpp create mode 100644 src/ChemistryTable.cpp create mode 100644 src/ChemistryTable.h create mode 100644 src/Compare.cpp create mode 100644 src/CompositeFastaReader.cpp create mode 100644 src/Config.cpp create mode 100644 src/DataSet.cpp create mode 100644 src/DataSetBaseTypes.cpp create mode 100644 src/DataSetElement.cpp create mode 100644 src/DataSetIO.cpp create mode 100644 src/DataSetIO.h create mode 100644 src/DataSetTypes.cpp create mode 100644 src/DataSetUtils.h create mode 100644 src/DataSetXsd.cpp create mode 100644 src/EntireFileQuery.cpp create mode 100644 src/FaiIndex.cpp create mode 100644 src/FaiZmwChunker.cpp create mode 100644 src/FaiZmwChunker.h create mode 100644 src/FastaCache.cpp create mode 100644 src/FastaReader.cpp create mode 100644 src/FastaSequence.cpp create mode 100644 src/FastaSequenceQuery.cpp create mode 100644 src/FastaWriter.cpp create mode 100644 src/FastqReader.cpp create mode 100644 src/FastqSequence.cpp create mode 100644 src/FastqWriter.cpp create mode 100644 src/FileProducer.cpp create mode 100644 src/FileProducer.h create mode 100644 src/FileUtils.cpp create mode 100644 src/FileUtils.h create mode 100644 src/FofnReader.cpp create mode 100644 src/FofnReader.h create mode 100644 src/FormatUtils.cpp create mode 100644 src/GenomicIntervalQuery.cpp create mode 100644 src/IFastaWriter.cpp create mode 100644 src/IFastqWriter.cpp create mode 100644 src/IRecordWriter.cpp create mode 100644 src/IndexedBamWriter.cpp create mode 100644 src/IndexedFastaReader.cpp create mode 100644 src/IndexedFastqBgzfReader.cpp create mode 100644 src/IndexedFastqBgzfReader.h create mode 100644 src/IndexedFastqReader.cpp create mode 100644 src/IndexedFastqReaderImpl.cpp create mode 100644 src/IndexedFastqReaderImpl.h create mode 100644 src/IndexedFastqTextReader.cpp create mode 100644 src/IndexedFastqTextReader.h create mode 100644 src/KSeqReader.cpp create mode 100644 src/KSeqReader.h create mode 100644 src/MD5.cpp create mode 100644 src/MemoryUtils.cpp create mode 100644 src/MemoryUtils.h create mode 100644 src/PbbamInternalConfig.h create mode 100644 src/PbiBuilder.cpp create mode 100644 src/PbiFile.cpp create mode 100644 src/PbiFilter.cpp create mode 100644 src/PbiFilterQuery.cpp create mode 100644 src/PbiFilterTypes.cpp create mode 100644 src/PbiIndexIO.cpp create mode 100644 src/PbiIndexIO.h create mode 100644 src/PbiIndexedBamReader.cpp create mode 100644 src/PbiRawData.cpp create mode 100644 src/ProgramInfo.cpp create mode 100644 src/Pulse2BaseCache.h create mode 100644 src/QNameQuery.cpp create mode 100644 src/ReadAccuracyQuery.cpp create mode 100644 src/ReadGroupInfo.cpp create mode 100644 src/RecordType.cpp create mode 100644 src/SamTagCodec.cpp create mode 100644 src/SamWriter.cpp create mode 100644 src/SequenceInfo.cpp create mode 100644 src/SequenceUtils.h create mode 100644 src/StringUtilities.cpp create mode 100644 src/SubreadLengthQuery.cpp create mode 100644 src/Tag.cpp create mode 100644 src/TagCollection.cpp create mode 100644 src/TextFileReader.cpp create mode 100644 src/TextFileWriter.cpp create mode 100644 src/TimeUtils.h create mode 100644 src/ValidationErrors.cpp create mode 100644 src/ValidationErrors.h create mode 100644 src/ValidationException.cpp create mode 100644 src/Validator.cpp create mode 100644 src/Version.cpp create mode 100644 src/Version.h create mode 100644 src/VirtualRegion.cpp create mode 100644 src/VirtualRegionTypeMap.cpp create mode 100644 src/VirtualStitching.h create mode 100644 src/VirtualZmwBamRecord.cpp create mode 100644 src/VirtualZmwCompositeReader.cpp create mode 100644 src/VirtualZmwCompositeReader.h create mode 100644 src/VirtualZmwReader.cpp create mode 100644 src/VirtualZmwReader.h create mode 100644 src/WhitelistedZmwReadStitcher.cpp create mode 100644 src/XmlReader.cpp create mode 100644 src/XmlReader.h create mode 100644 src/XmlWriter.cpp create mode 100644 src/XmlWriter.h create mode 100644 src/ZmwChunkedFastaReader.cpp create mode 100644 src/ZmwChunkedFastqReader.cpp create mode 100644 src/ZmwChunkedFastxBgzfReader.cpp create mode 100644 src/ZmwChunkedFastxBgzfReader.h create mode 100644 src/ZmwChunkedFastxReaderImpl.cpp create mode 100644 src/ZmwChunkedFastxReaderImpl.h create mode 100644 src/ZmwChunkedFastxTextReader.cpp create mode 100644 src/ZmwChunkedFastxTextReader.h create mode 100644 src/ZmwGroupQuery.cpp create mode 100644 src/ZmwQuery.cpp create mode 100644 src/ZmwReadStitcher.cpp create mode 100644 src/ZmwTypeMap.cpp create mode 100644 src/bed/BedReader.cpp create mode 100644 src/bed/BedWriter.cpp create mode 100644 src/ccs/CCSPbiBuilder.cpp create mode 100644 src/ccs/CCSRecordFormat.cpp create mode 100644 src/ccs/CCSRecordReader.cpp create mode 100644 src/ccs/CCSRecordWriter.cpp create mode 100644 src/meson.build create mode 100644 src/pugixml/pugiconfig.hpp create mode 100644 src/pugixml/pugixml.cpp create mode 100644 src/pugixml/pugixml.hpp create mode 100644 src/vcf/VcfFile.cpp create mode 100644 src/vcf/VcfFormat.cpp create mode 100644 src/vcf/VcfHeader.cpp create mode 100644 src/vcf/VcfHeaderTypes.cpp create mode 100644 src/vcf/VcfQuery.cpp create mode 100644 src/vcf/VcfReader.cpp create mode 100644 src/vcf/VcfSort.cpp create mode 100644 src/vcf/VcfVariant.cpp create mode 100644 src/vcf/VcfWriter.cpp create mode 100644 subprojects/gtest.wrap create mode 100644 subprojects/htslib.wrap create mode 100644 subprojects/pbcopper.wrap create mode 100644 subprojects/zlib.wrap create mode 100644 tests/data/aligned.bam create mode 100644 tests/data/aligned.bam.bai create mode 100644 tests/data/aligned.bam.pbi create mode 100644 tests/data/aligned.sam create mode 100644 tests/data/aligned2.bam create mode 100644 tests/data/aligned2.bam.bai create mode 100644 tests/data/aligned2.bam.pbi create mode 100644 tests/data/barcoded_read_groups.bam create mode 100644 tests/data/barcoded_read_groups.bam.pbi create mode 100644 tests/data/bed/test.bed create mode 100644 tests/data/bed/test.bed.gz create mode 100644 tests/data/chemistry.xml create mode 100644 tests/data/chimera_minimal.fasta create mode 100644 tests/data/chunking/chunking.subreadset.xml create mode 100644 tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.1.subreads.bam create mode 100644 tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.1.subreads.bam.pbi create mode 100644 tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.2.subreads.bam create mode 100644 tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.2.subreads.bam.pbi create mode 100644 tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.3.subreads.bam create mode 100644 tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.3.subreads.bam.pbi create mode 100644 tests/data/clip_to_query.bam create mode 100644 tests/data/dataset/ali1.xml create mode 100644 tests/data/dataset/ali2.xml create mode 100644 tests/data/dataset/ali3.xml create mode 100644 tests/data/dataset/ali4.xml create mode 100644 tests/data/dataset/bam_mapping.bam create mode 100644 tests/data/dataset/bam_mapping.bam.pbi create mode 100644 tests/data/dataset/bam_mapping_1.bam create mode 100644 tests/data/dataset/bam_mapping_1.bam.pbi create mode 100644 tests/data/dataset/bam_mapping_2.bam create mode 100644 tests/data/dataset/bam_mapping_2.bam.pbi create mode 100644 tests/data/dataset/bam_mapping_new.bam create mode 100644 tests/data/dataset/bam_mapping_new.bam.pbi create mode 100644 tests/data/dataset/bam_mapping_staggered.xml create mode 100644 tests/data/dataset/barcode.dataset.xml create mode 100644 tests/data/dataset/biosample.subreadset.xml create mode 100644 tests/data/dataset/ccsread.dataset.xml create mode 100644 tests/data/dataset/lambda_contigs.xml create mode 100644 tests/data/dataset/malformed.xml create mode 100644 tests/data/dataset/pbalchemy10kbp.xml create mode 100644 tests/data/dataset/qname_filter.bam create mode 100644 tests/data/dataset/qname_filter.bam.pbi create mode 100644 tests/data/dataset/reference.dataset.xml create mode 100644 tests/data/dataset/subread_dataset1.xml create mode 100644 tests/data/dataset/subread_dataset2.xml create mode 100644 tests/data/dataset/subread_dataset3.xml create mode 100644 tests/data/dataset/transformed_rs_subread_dataset.xml create mode 100644 tests/data/empty.bam create mode 100644 tests/data/empty.bam.pbi create mode 100644 tests/data/fastx/chunking.fa create mode 100644 tests/data/fastx/chunking.fa.fai create mode 100644 tests/data/fastx/chunking.fq create mode 100644 tests/data/fastx/chunking.fq.fai create mode 100644 tests/data/fastx/simple-bgzf.fa.gz create mode 100644 tests/data/fastx/simple-bgzf.fa.gz.fai create mode 100644 tests/data/fastx/simple-bgzf.fa.gz.gzi create mode 100644 tests/data/fastx/simple-bgzf.fq.gz create mode 100644 tests/data/fastx/simple-bgzf.fq.gz.fai create mode 100644 tests/data/fastx/simple-bgzf.fq.gz.gzi create mode 100644 tests/data/fastx/simple-gzip.fa.gz create mode 100644 tests/data/fastx/simple-gzip.fq.gz create mode 100644 tests/data/fastx/simple.fa create mode 100644 tests/data/fastx/simple.fa.fai create mode 100644 tests/data/fastx/simple.fq create mode 100644 tests/data/fastx/simple.fq.fai create mode 100644 tests/data/fastx/windows_formatted.fasta create mode 100644 tests/data/fastx/windows_formatted.fastq create mode 100644 tests/data/group/group.fofn.in create mode 100644 tests/data/group/test1.bam create mode 100644 tests/data/group/test2.bam create mode 100644 tests/data/group/test2.bam.pbi create mode 100644 tests/data/group/test3.bam create mode 100644 tests/data/lambdaNEB.fa create mode 100644 tests/data/lambdaNEB.fa.fai create mode 100644 tests/data/long-cigar-1.7.bam create mode 100644 tests/data/long_reads.bam create mode 100644 tests/data/merge.fofn create mode 100644 tests/data/pbbamify/input-aligned-1.bam create mode 100644 tests/data/pbbamify/input-aligned-2.bam create mode 100644 tests/data/pbbamify/input-aligned-3.bam create mode 100644 tests/data/pbbamify/input-aligned-all.bam create mode 100644 tests/data/pbbamify/synthetic-ref-1.fa create mode 100644 tests/data/pbbamify/synthetic-ref-1.fa.fai create mode 100644 tests/data/pbbamify/synthetic_movie_1.subreads.bam create mode 100644 tests/data/pbbamify/synthetic_movie_1.subreads.bam.bai create mode 100644 tests/data/pbbamify/synthetic_movie_1.subreads.bam.pbi create mode 100644 tests/data/pbbamify/synthetic_movie_2.subreads.bam create mode 100644 tests/data/pbbamify/synthetic_movie_2.subreads.bam.bai create mode 100644 tests/data/pbbamify/synthetic_movie_2.subreads.bam.pbi create mode 100644 tests/data/pbbamify/synthetic_movie_3.subreads.bam create mode 100644 tests/data/pbbamify/synthetic_movie_3.subreads.bam.bai create mode 100644 tests/data/pbbamify/synthetic_movie_3.subreads.bam.pbi create mode 100644 tests/data/pbbamify/synthetic_movie_all.subreadset.xml.in create mode 100644 tests/data/phi29.bam create mode 100644 tests/data/phi29.bam.pbi create mode 100644 tests/data/polymerase/consolidate.subread.dataset.xml create mode 100644 tests/data/polymerase/filtered_resources.subread.dataset.xml create mode 100644 tests/data/polymerase/internal.hqregions.bam create mode 100644 tests/data/polymerase/internal.hqregions.bam.pbi create mode 100644 tests/data/polymerase/internal.lqregions.bam create mode 100644 tests/data/polymerase/internal.lqregions.bam.pbi create mode 100644 tests/data/polymerase/internal.polymerase.bam create mode 100644 tests/data/polymerase/internal.polymerase.bam.pbi create mode 100644 tests/data/polymerase/internal.scraps.bam create mode 100644 tests/data/polymerase/internal.scraps.bam.pbi create mode 100644 tests/data/polymerase/internal.subreads.bam create mode 100644 tests/data/polymerase/internal.subreads.bam.pbi create mode 100644 tests/data/polymerase/multiple_resources.subread.dataset.xml create mode 100644 tests/data/polymerase/production.polymerase.bam create mode 100644 tests/data/polymerase/production.scraps.bam create mode 100644 tests/data/polymerase/production.scraps.bam.pbi create mode 100644 tests/data/polymerase/production.subreads.bam create mode 100644 tests/data/polymerase/production.subreads.bam.pbi create mode 100644 tests/data/polymerase/production_hq.hqregion.bam create mode 100644 tests/data/polymerase/production_hq.hqregion.bam.pbi create mode 100644 tests/data/polymerase/production_hq.scraps.bam create mode 100644 tests/data/polymerase/production_hq.scraps.bam.pbi create mode 100644 tests/data/polymerase/qnameFiltered.subreads.dataset.xml create mode 100644 tests/data/polymerase/qname_whitelist.txt create mode 100644 tests/data/polymerase/scrapless.scraps.bam create mode 100644 tests/data/polymerase/scrapless.scraps.bam.pbi create mode 100644 tests/data/polymerase/scrapless.subreads.bam create mode 100644 tests/data/polymerase/scrapless.subreads.bam.pbi create mode 100644 tests/data/referenceset.xml create mode 100644 tests/data/refskip.bam create mode 100644 tests/data/relative/a/test.bam create mode 100644 tests/data/relative/b/test1.bam create mode 100644 tests/data/relative/b/test2.bam create mode 100644 tests/data/relative/relative.fofn create mode 100644 tests/data/relative/relative.xml create mode 100644 tests/data/relative/relative2.fofn create mode 100644 tests/data/segfault.bam create mode 100644 tests/data/softclip_deletions.bam create mode 100644 tests/data/stitching/test_qstart.scraps.bam create mode 100644 tests/data/stitching/test_qstart.scraps.bam.pbi create mode 100644 tests/data/stitching/test_qstart.subreads.bam create mode 100644 tests/data/stitching/test_qstart.subreads.bam.pbi create mode 100644 tests/data/test_GenomicIntervals/adjacent_intervals.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/contig_name_only.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/disjoint_intervals.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/empty.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/invalid_missing_rname.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/invalid_rname_operator.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/invalid_tstart_operator.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/no_filter.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/out_of_range.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/single_interval.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/single_interval_end_gte.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/single_interval_start_lte.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/test_contigs.bam create mode 100644 tests/data/test_GenomicIntervals/test_contigs.bam.pbi create mode 100644 tests/data/test_GenomicIntervals/test_contigs.fasta create mode 100644 tests/data/test_GenomicIntervals/two_contigs.alignmentset.xml create mode 100644 tests/data/test_GenomicIntervals/whole_contig.alignmentset.xml create mode 100644 tests/data/test_group_query/group.fofn.in create mode 100644 tests/data/test_group_query/test1.bam create mode 100644 tests/data/test_group_query/test2.bam create mode 100644 tests/data/test_group_query/test2.bam.pbi create mode 100644 tests/data/test_group_query/test3.bam create mode 100644 tests/data/transcript.subreads.bam create mode 100644 tests/data/transcript.subreads.bam.pbi create mode 100644 tests/data/transcriptset.xml create mode 100644 tests/data/unmap1.bam create mode 100644 tests/data/unmap1.bam.bai create mode 100644 tests/data/unmap2.bam create mode 100644 tests/data/unmap2.bam.bai create mode 100644 tests/data/vcf/structural_variants.vcf create mode 100644 tests/data/vcf/unsorted.vcf create mode 100644 tests/meson.build create mode 100755 tests/scripts/generate_data.py create mode 100644 tests/src/FastxTests.h create mode 100644 tests/src/PbbamTestData.h.in create mode 100644 tests/src/cram/bam2sam.t.in create mode 100644 tests/src/cram/pbbamify.t.in create mode 100644 tests/src/cram/pbindexdump_cpp.t.in create mode 100644 tests/src/cram/pbindexdump_json.t.in create mode 100644 tests/src/cram/pbmerge_aligned_ordering.t.in create mode 100644 tests/src/cram/pbmerge_dataset.t.in create mode 100644 tests/src/cram/pbmerge_fofn.t.in create mode 100644 tests/src/cram/pbmerge_mixed_ordering.t.in create mode 100644 tests/src/cram/pbmerge_pacbio_ordering.t.in create mode 100644 tests/src/meson.build create mode 100644 tests/src/test_AlignmentPrinter.cpp create mode 100644 tests/src/test_BamFile.cpp create mode 100644 tests/src/test_BamHeader.cpp create mode 100644 tests/src/test_BamRecord.cpp create mode 100644 tests/src/test_BamRecordBuilder.cpp create mode 100644 tests/src/test_BamRecordClipping.cpp create mode 100644 tests/src/test_BamRecordImplCore.cpp create mode 100644 tests/src/test_BamRecordImplTags.cpp create mode 100644 tests/src/test_BamRecordImplVariableData.cpp create mode 100644 tests/src/test_BamRecordMapping.cpp create mode 100644 tests/src/test_BamWriter.cpp create mode 100644 tests/src/test_BarcodeQuery.cpp create mode 100644 tests/src/test_BedReader.cpp create mode 100644 tests/src/test_BedWriter.cpp create mode 100644 tests/src/test_BgzipFastaWriter.cpp create mode 100644 tests/src/test_BgzipFastqWriter.cpp create mode 100644 tests/src/test_BgzipWriter.cpp create mode 100644 tests/src/test_CCSPbiBuilder.cpp create mode 100644 tests/src/test_CCSRecordIO.cpp create mode 100644 tests/src/test_Cigar.cpp create mode 100644 tests/src/test_Compare.cpp create mode 100644 tests/src/test_DataSetCore.cpp create mode 100644 tests/src/test_DataSetIO.cpp create mode 100644 tests/src/test_DataSetQuery.cpp create mode 100644 tests/src/test_DataSetXsd.cpp create mode 100644 tests/src/test_EndToEnd.cpp create mode 100644 tests/src/test_EntireFileQuery.cpp create mode 100644 tests/src/test_FaiIndex.cpp create mode 100644 tests/src/test_FaiZmwChunker.cpp create mode 100644 tests/src/test_FastaReader.cpp create mode 100644 tests/src/test_FastaSequence.cpp create mode 100644 tests/src/test_FastaSequenceQuery.cpp create mode 100644 tests/src/test_FastaWriter.cpp create mode 100644 tests/src/test_FastqReader.cpp create mode 100644 tests/src/test_FastqSequence.cpp create mode 100644 tests/src/test_FastqWriter.cpp create mode 100644 tests/src/test_FileUtils.cpp create mode 100644 tests/src/test_Frames.cpp create mode 100644 tests/src/test_GenomicIntervalQuery.cpp create mode 100644 tests/src/test_GenomicIntervals.cpp create mode 100644 tests/src/test_IndexedBamWriter.cpp create mode 100644 tests/src/test_IndexedFastaReader.cpp create mode 100644 tests/src/test_IndexedFastqReader.cpp create mode 100644 tests/src/test_LongCigar.cpp create mode 100644 tests/src/test_PacBioIndex.cpp create mode 100644 tests/src/test_PbiFilter.cpp create mode 100644 tests/src/test_PbiFilterQuery.cpp create mode 100644 tests/src/test_Pulse2BaseCache.cpp create mode 100644 tests/src/test_QNameQuery.cpp create mode 100644 tests/src/test_QualityValues.cpp create mode 100644 tests/src/test_ReadAccuracyQuery.cpp create mode 100644 tests/src/test_ReadGroupInfo.cpp create mode 100644 tests/src/test_SamWriter.cpp create mode 100644 tests/src/test_SequenceUtils.cpp create mode 100644 tests/src/test_StringUtils.cpp create mode 100644 tests/src/test_SubreadLengthQuery.cpp create mode 100644 tests/src/test_Tags.cpp create mode 100644 tests/src/test_TextFileReader.cpp create mode 100644 tests/src/test_TextFileWriter.cpp create mode 100644 tests/src/test_TimeUtils.cpp create mode 100644 tests/src/test_Validator.cpp create mode 100644 tests/src/test_VcfFile.cpp create mode 100644 tests/src/test_VcfFormat.cpp create mode 100644 tests/src/test_VcfHeader.cpp create mode 100644 tests/src/test_VcfQuery.cpp create mode 100644 tests/src/test_VcfReader.cpp create mode 100644 tests/src/test_VcfSort.cpp create mode 100644 tests/src/test_VcfVariant.cpp create mode 100644 tests/src/test_VcfWriter.cpp create mode 100644 tests/src/test_Version.cpp create mode 100644 tests/src/test_WhitelistedZmwReadStitcher.cpp create mode 100644 tests/src/test_ZmwChunkedFastxReader.cpp create mode 100644 tests/src/test_ZmwQuery.cpp create mode 100644 tests/src/test_ZmwReadStitcher.cpp create mode 100644 tools/bam2sam/src/Bam2SamSettings.cpp create mode 100644 tools/bam2sam/src/Bam2SamSettings.h create mode 100644 tools/bam2sam/src/Bam2SamVersion.h.in create mode 100644 tools/bam2sam/src/Bam2SamWorkflow.cpp create mode 100644 tools/bam2sam/src/Bam2SamWorkflow.h create mode 100644 tools/bam2sam/src/main.cpp create mode 100755 tools/check-formatting create mode 100755 tools/format-all create mode 100755 tools/git-clang-format create mode 100644 tools/meson.build create mode 100644 tools/pbbamify/src/PbBamifySettings.cpp create mode 100644 tools/pbbamify/src/PbBamifySettings.h create mode 100644 tools/pbbamify/src/PbBamifyVersion.h.in create mode 100644 tools/pbbamify/src/PbBamifyWorkflow.cpp create mode 100644 tools/pbbamify/src/PbBamifyWorkflow.h create mode 100644 tools/pbbamify/src/QueryLookup.cpp create mode 100644 tools/pbbamify/src/QueryLookup.h create mode 100644 tools/pbbamify/src/main.cpp create mode 100644 tools/pbindex/src/PbIndexSettings.cpp create mode 100644 tools/pbindex/src/PbIndexSettings.h create mode 100644 tools/pbindex/src/PbIndexVersion.h.in create mode 100644 tools/pbindex/src/PbIndexWorkflow.cpp create mode 100644 tools/pbindex/src/PbIndexWorkflow.h create mode 100644 tools/pbindex/src/main.cpp create mode 100644 tools/pbindexdump/src/CppFormatter.cpp create mode 100644 tools/pbindexdump/src/CppFormatter.h create mode 100644 tools/pbindexdump/src/JsonFormatter.cpp create mode 100644 tools/pbindexdump/src/JsonFormatter.h create mode 100644 tools/pbindexdump/src/PbIndexDumpSettings.cpp create mode 100644 tools/pbindexdump/src/PbIndexDumpSettings.h create mode 100644 tools/pbindexdump/src/PbIndexDumpVersion.h.in create mode 100644 tools/pbindexdump/src/PbIndexDumpWorkflow.cpp create mode 100644 tools/pbindexdump/src/PbIndexDumpWorkflow.h create mode 100644 tools/pbindexdump/src/main.cpp create mode 100644 tools/pbmerge/src/PbMergeSettings.cpp create mode 100644 tools/pbmerge/src/PbMergeSettings.h create mode 100644 tools/pbmerge/src/PbMergeVersion.h.in create mode 100644 tools/pbmerge/src/PbMergeWorkflow.cpp create mode 100644 tools/pbmerge/src/PbMergeWorkflow.h create mode 100644 tools/pbmerge/src/main.cpp diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1519f35 --- /dev/null +++ b/.clang-format @@ -0,0 +1,13 @@ +BasedOnStyle: Google +BreakBeforeBraces: Mozilla + +AllowShortLoopsOnASingleLine: false +AccessModifierOffset: -4 +BreakConstructorInitializersBeforeComma: true +ColumnLimit: 100 +IndentWidth: 4 +PointerAlignment: Left +TabWidth: 4 + +ReflowComments: false # protect ASCII art in comments +KeepEmptyLinesAtTheStartOfBlocks: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c26bb9a --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +/build* + +# cram +*.pyc + +# Meson WrapDB stuff +/subprojects/* +!/subprojects/*.wrap diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..33b861e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,61 @@ +language: cpp +compiler: + - gcc + +before_install: + + # Travis's default installs of gcc, boost, & cmake currently lag behind the minimums we need. + # So we need to manually setup them up. + # + # - gcc 4.8 (current default on Travis is 4.7, which is no good for C++11 work) + # - boost 1.55 + # - cmake 3.x + + # add external repos + - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test # gcc + - sudo add-apt-repository -y ppa:boost-latest/ppa # boost + - sudo add-apt-repository -y ppa:george-edison55/precise-backports # cmake + + # remove existing cmake install + - sudo apt-get remove -qq cmake cmake-data + - sudo apt-get autoremove -qq + + # update apt + - sudo apt-get update -y -qq + + # install + - sudo apt-get install -y -qq g++-4.8 boost1.55 cmake-data cmake + + # make sure we're using new gcc tools + - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90 + - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 90 + - sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-4.8 90 + + # prep zlib + - sudo apt-get install -y -qq zlib1g-dev + + # prep GoogleTest + - sudo apt-get install -y -qq libgtest-dev + +before_script: + # run cmake + - mkdir build + - cd build + - cmake .. -DGTEST_SRC_DIR=/usr/src/gtest -DCMAKE_BUILD_TYPE=Debug + +script: + # build & test + - make -j 3 + - make test + +branches: + only: + - master + +notifications: + recipients: + - dbarnett@pacb.com + email: + on_success: change + on_failure: always + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..86c13c0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,621 @@ +# PacBio::BAM - change log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## Active + +### Added + - CCSRecord API to work with the minimally required data for CCS + - TextFileReader & TextFileWriter for generic line files (plain text or gzipped) + - BedReader & BedWriter for BED format support + +## [1.0.6] - 2019-06-14 + +### Added + - IFastaWriter & IFastqWriter abstract base classes + +## [1.0.5] - 2019-06-11 + +### Changed + - BAM tag lookup improvements under the hood. + +## [1.0.4] - 2019-06-07 + +### Added + - General-purpose BgzipWriter + - BgzipFastaWriter and BgzipFastqWriter + - Read-only view to read indices passing a PbiFilter + - IPD field to SimpleRead + +## [1.0.3] - 2019-05-20 + +### Added + - IndexedFastqReader for random access to FASTQ subregions + +### Fixed + - MappedSimpleRead clipping: on disjoint aligned/requested regions and on requests larger + than available sequence. + +## [1.0.2] - 2019-05-10 + +### Added + - Range-for iteration on FastaReader & FastqReader + +## [1.0.1] - 2019-05-09 + +### Added + - SimpleRead & MappedSimpleRead for htslib-free processing. + +### Fixed + - Incorrect type displayed in SAM output (pure-text) for floating-point values. + +## [1.0.0] - 2019-04-22 + +### Changed + - C++14 is now a *hard* minimum. + +### Removed + - Headers emulating C++14 features for C++11. + +### Fixed + - Inconsistent whitelist/blacklist filters in DataSet XML. + +## [0.25.0] - 2019-04-11 + +### Changed + - Requires C++14 at minimum. + +### Fixed + - Reading BioSample(s) elements from DataSet XML. + +## [0.24.0] - 2019-04-05 + +### Added + - Built-in support for dataset elements: BioSample(s) & DNABarcode(s). + - BaiIndexCache for reusing data from *.bai files(s). + - Support in GenomicIntervalQuery for new BaiIndexCache. + +## [0.23.1] - 2019-03-21 + +### Added + - Streamable BamReader (via stdin). + - Enabled range-for on BamReader, compatible with the other *Query inputs. + +## [0.23.0] - 2019-03-11 + +### Added + - PbiIndexCache and FastaCache for reusing file data + - BaiIndexedBamReader and GenomicIntervalQuery can be constructed without + initial interval. + +## [0.22.0] - 2019-02-11 + +### Fixed + - Handles zero-length reads for stitching ZMW reads. + - Clipping to query on reverse-strand aligned reads. + - Removed UB in dataset API. + +### Added + - "exciseFlankingInserts" option for clipping reads w.r.t reference. + +## [0.21.0] - 2018-12-21 + +### Added + - New local context flags: ADAPTER_BEFORE_BAD and ADAPTER_AFTER_BAD. + +### Changed + - Current PacBioBAM spec now 3.0.7. + +### Removed + - CMake has been removed completely. + +## [0.20.0] - 2018-10-03 + +### Added + - Support for (optionally) barcode-labeled read group IDs. + +## [0.19.0] - 2018-09-11 + +### Added + - TranscriptAlignmentSet to XML support + +## [0.17.0] - 2018-03-18 + +### Added +- CompressionLevel/NumThreads parameter implementation to PbiBuilder. +- Dataset ctor to PbiFileQuery. +- TranscriptSet to XML support. +- Auto-enabled "permissive CIGAR mode" for pbbamify tool. +- IndexedBamWriter, for more efficient writing of BAM & PBI simultaneously. + +## [0.16.0] - 2018-01-17 + +### Removed +- Removed the PbiIndex class and its "lookup data"-related helpers. These were +never as useful as initially intended. PbiRawData and its related classes are the +recommended interface for working with PBI index data. + +## [0.15.0] - 2018-01-12 + +### Added +- Support for long CIGARs (>64K operations). + +## [0.14.0] - 2017-12-12 + +### Added +- Support for newer style QNAMEs. Recent version of htslib (1.4+) have started +adding extra null terminators to make the subsequent CIGAR section 32-bit aligned. + +### Changed +- Requirements for htslib version used. Must now be htslib v1.4+. + +## [0.13.2] - 2017-09-25 + +### Added +- Backward compatibility for C++11 (std::make_unique which is 11/14 agnostic). + +## [0.13.1] - 2017-09-25 + +### Added +- Support for "pe" tag in stitched, virtual reads. + +## [0.13.0] - 2017-09-25 + +### Changed +- Ran clang-tidy (modernize) over codebase to clean up legacy coding styles. + +## [0.12.2] - 2017-09-22 + +### Added +- HasPulseExclusion() to BamRecord (& derived types). + +## [0.12.1] - 2017-09-21 + +### Added +- Pulse exclusion base feature to read group. + +## [0.12.0] - 2017-09-19 + +### Added +- NumReads() for PBI filter-based queries. This allows fetching of the number +of reads that pass the filter, without needing to iterate over the entire +file(s). + +## [0.11.0] - 2017-09-15 + +### Added +- Support for internal tag: pulse exclusion reason ("pe"). New methods on +BamRecord, and new enum PulseExclusionReason. + +### Changed +- Default PacBioBAM format version now 3.0.5 + +## [0.10.2] - 2017-09-14 + +### Changed +- Explicitly trim all whitespace from FASTA input. + +## [0.10.1] - 2017-09-11 + +### Changed +- Frames, add mutex to avoid race condition in InitIpdDownsampling(void) + +## [0.10.0] - 2017-09-08 + +### Changed +- PbiBuilder backend for generating PBI index files "on-the-fly" along with +writing BAM files. The previous implementation's memory usage scaled linearly +with the number of reads, sometimes reaching huge numbers (several gigs or more). +The new implementation's memory usage remains constant for any number of reads, +without any runtime hit on files/architectures tested. + +### Removed +- PbiBuilder::Result(). Returned an intermediate snapshot of the index under +construction. This method isn't usable with the new PbiBuilder backend and was +really only useful for initial debugging/testing. It is no longer used in the +test framework and is unlikely to be used by client code either. Dropping this +method from the API, and thus bumping the version number. + +## [0.9.0] - 2017-08-07 + +### Removed +- Bundled htslib. Now using 'stock' htslib (v1.3.1+). +- Built-in SWIG wrappers. + +## [0.8.0] - 2017-07-24 + +### Added +- Default DataSet 'Version' attribute if none already present (currently 4.0.0) +- Added whitelist support for filtering ZMWs via DataSetXML. +- Added iterable query over FASTA files & ReferenceSet datasets. +- Added DataSet::AllFiles to access primary resources AND their child files (indices, +scraps, etc). + +### Fixed +- Bug in the build system preventing clean rebuilds. + +### Removed +- Dropped the bundled, PacBio-forked version of htslib. Now using stock htslib (v1.3.1+). + +## [0.7.4] - 2016-11-18 + +### Changed +- Compatibility for merging BAM files no longer requires exact match of PacBioBAM +version number (header @HD:pb tag). As long as both files meet the minimum +supported version number, the merge is allowed. + +## [0.7.3] - 2016-11-11 + +### Added +- Support for S/P2-C2 chemistry and forthcoming 4.0 basecaller + +## [0.7.2] - 2016-11-10 + +### Removed +- SAM header version equality check for merging BAM files. PacBioBAM version +number carries more meaning for PacBio data and thus will be the basis of +ensuring compatible merging. + +## [0.7.1] - 2016-11-09 + +### Added +- (Unindexed) FASTA reader & FastaSequence data structure. +- Missing unit tests for internal BAM tag access. +- Chemistry data for basecaller v3.3. +- Missing parsers for filtering barcode quality ("bq"), barcode forward ("bcf"), +and barcode reverse ("bcr") from DataSetXML. +- Integrated htslib into project. + +### Fixed +- Reverse complement on padding base. + +## [0.7.0] - 2016-09-26 + +### Added +- Clipping for CCS records + +### Fixed +- Cached position data leaking across records while iterating. +- Rolled back default pulse behavior in internal BAM API, to be backward- +compatible with existing client code (for now at least). v0.6.0 introduced +returning basecalled positions ONLY by default, rather than return ALL +pulses. +- Fixed crash when attempting to read from empty BAM/PBI files using the +PbiFilter-enabled APIs. + +## [0.6.0] - 2016-09-13 + +### Added +- BamWriter writes to a BAM file with the target name plus a ".tmp" suffix. On +successful completion (i.e. normal BamWriter destruction, not triggered by a +thrown exception) the file is renamed to the actual requested filename. +- PBI file creation follows the same temporary naming convention. +- Support for barcode pair (forward, reverse) in DataSetXML filter. +- Validation API & 'auto-validate' compile-time switch. +- Added support for a batched QNAME whitelist filter in DataSet XML. Uses (new) +Property name 'qname_file', with the value being the filepath containing the +whitelist. +- Exposed MD5 hashing to API. +- Ability to remove base features from a ReadGroupInfo object. +- Can construct an aggregate PbiRawData index object from a DataSet: essentially +concatenates all PBI data within the dataset. +- New SamWriter class to create SAM-formatted output of PacBio BAM data. +- Extended APIs for accessing "internal BAM" data, including PulseBehavior +switch for selecting between all pulses & basecalls only. + +### Fixed +- Improper 'clip to reference' product for BamRecord in some cases. +- Improper behavior in tag accessors (e.g. BamRecord::IPD()) on reverse strand- +aligned reads (bug 31339). +- Improper basecaller version parsing in ReadGroupInfo. + +### Changed +- RecordType::POLYMERASE renamed to RecordType::ZMW to reflect changes in +PacBio BAM spec v3.0.4 +- Refactored the 'virtual' reader classes - to match the new nomenclature, +and to combine the virtual reader & composite readers behind a shared +interface. The old class names still exist, as typedefs to the new ones, +and the interfaces are completely source-compatible - so as not to break +existing code. However, the old classes should be considered deprecated and +the new ones preferred. Below is the mapping of old -> new: + + VirtualPolymeraseBamRecord -> VirtualZmwBamRecord + VirtualPolymeraseReader -> ZmwReadStitcher + VirtualPolymeraseCompositeReader -> ZmwReadStitcher + ZmwWhitelistVirtualReader -> WhitelistedZmwReadStitcher + + +## [0.5.0] - 2016-02-22 + +### Added +- Platform model tag added to read group as RG::PM +- New scrap zmw type sz +- pbmerge accepts DataSetXML as input - using top-level resource BAMs as input, +applying filters, and generating a merged BAM. Also added FOFN support, instead +of listing out BAMs as command line args. +- PbiLocalContextFilter to allow filtering on subread local context. +- PbiBuilder: multithreading & zlib compression-level tuning for PBI output + +### Fixed +- Fixed mishandling of relative BAM filenames in the filename constructor for +DataSet (e.g. DataSet ds("../data.bam")). + +## [0.4.5] - 2016-01-14 + +### Changed +- PbiFilterQuery (and any other PBI-backed query, e.g. ZmwQuery ) now throws if +PBI file(s) missing insted of returning empty result. +- GenomicIntervalQuery now throws if BAI file(s) missing instead of returning +empty result. +- BamFile will throw if file is truncated (e.g. missing the EOF block). Disable +by defining PBBAM_NO_CHECK_EOF . + +## [0.4.4] - 2016-01-07 + +### Added +- bam2sam command line utility. The primary benefit is removing the dependency +on samtools during tests, but also provides users a functioning BAM -> SAM +converter in the absence of samtools. +- pbmerge command line utility. Allows merging N BAM files into one, optionally +creating the PBI file alongside. +- Added BamRecord::Pkmean2 & Pkmid2, 2D equivalent of Pkmean/Pkmid, for internal +BAMs. + +### Removed +- samtools dependency + +## [0.4.3] - 2015-12-22 + +### Added +- Compile using ccache by default, if available. Can be manually disabled using +-DPacBioBAM_use_ccache=OFF with cmake. +- pbindexdump: command-line utility that converts PBI file data into human- +readable formats. (JSON by default). + +### Changed +- CMake option PacBioBAM_build_pbindex is being deprecated. Use +PacBioBAM_build_tools instead. + +## [0.4.2] - 2015-12-22 + +### Changed +- BamFile::PacBioIndexExists & StandardIndexExists no longer check timestamps. +Copying/moving files around can yield timestamps that are not helpful (no longer +guaranteed that the .pbi will be "newer" than the .bam, even though no content +changed). Added methods (e.g. bool BamFile::PacBioIndexIsNewer()) to do that +lookup if needed, but it is no longer done automatically. + +## [0.4.1] - 2015-12-18 + +### Added +- BamRecord::HasNumPasses + +### Changed +- VirtualPolymeraseBamRecord::VirtualRegionsTable(type) returns an empty vector +of regions if none are associated with the requested type, instead of throwing. + +## [0.4.0] - 2015-12-15 + +### Changed +- Redesigned PbiFilter interface and backend. Previous implementation did not +scale well as intermediate results were far too unwieldy. This redesign provides +speedups of orders of magnitude in many cases. + +## [0.3.2] - 2015-12-10 + +### Added +- Support for ReadGroupInfo sequencing chemistry data. +InvalidSequencingChemistryException thrown if an unsupported combination is +encountered. +- VirtualPolymeraseCompositeReader - for re-stitching records, across multiple +resources (e.g. from DataSetXML). Reader respects DataSet filter criteria. + +## [0.3.1] - 2015-10-30 + +### Added +- ZmwWhitelistVirtualReader: similar to VirtualPolymeraseReader but restricts +iteration to a whitelist of ZMW hole numbers, leveraging PBI index data for +random-access. + +### Fixed +- Fixed error in PBI construction, in which entire file sections (e.g. +BarcodeData or MappedData) where being dropped when any one record lacked data. +Correct behavior is to allow file section ommission if all records lack that +data type. + +## [0.3.0] - 2015-10-29 + +### Fixed +- Improper reporting of current offset from multi-threaded BamWriter. This had +the effect of creating broken PBIs that were written alongside the BAM. Added a +flush step, which incurs a performance hit, but restores correctness. + +## [0.2.4] - 2015-10-26 + +### Fixed +- Empty PbiFilter now returns all records, instead of filtering away all records. + +## [0.2.3] - 2015-10-26 + +### Added/Fixed +- Syncing DataSetXML across APIs. Primary changes include output of Version +attribute ("3.0.1") on appropriate elements, as well as resolution of namespace +issues. + +## [0.2.2] - 2015-10-22 + +### Added +- Added BAI bin calculation to BamWriter::Write, to ensure maximal compatibility +with downstream tools (e.g. 'samtools index'). A new BinCalculationMode enum +flag in BamWriter constructor cotnrols whether this behavior is enabled[default] +or not. + +## [0.2.1] - 2015-10-19 + +### Added +- Exposed the following classes to public API: + - BamReader + - BaiIndexedBamReader + - PbiIndexedBamReader + - GenomicIntervalCompositeBamReader + - PbiFilterCompositeBamReader + +## [0.2.0] - 2015-10-09 + +### Changed +- BAM spec v3.0.1 compliance. Previous (betas) versions of the BAM spec are not +supported and will causean exception to be throw if encountered. +- PBI lookup interface & backend, see PbiIndex.h & PbiLookupData.h for details. + +### Added +- BamFile::PacBioIndexExists() & BamFile::StandardIndexExists() - query the +existence of index files without auto-building them if they are missing, as in +BamFile::Ensure*IndexExists(). +- GenomicInterval now accepts an htslib/samtools-style REGION string in the +constructor: GenomicInterval("chr1:1000-2000"). Please note though, that pbbam +uses 0-based coordinates throughout, whereas samtools expects 1-based. The above +string is equivalent to "chr1:1001-2000" in samtools. +- Built-in PBI filters. See PbiFlter.h & PbiFilterTypes.h for built-in filters +and constructing composite filters. These can be used in conjunction with the +new PbiFilterQuery, which takes a generic PbiFilter and applies that to a +DataSet for iteration. +- New built-in queries: BarcodeQuery, ReadAccuracyQuery, SubreadLengthQuery. +These leverage the new filter API to construct a PbiFilter and apply to a +DataSet. +- Built-in BamRecord comparators that are STL-compatible. See Compare.h for full +list. This allows for statements like the following, which sorts records by ZMW +number: +``` c++ + vector data; + std::sort(data.begin(), data.end(), Compare::Zmw()); +``` +- "exciseSoftClips" option to BamRecord::CigarData() + +## [0.1.0] - 2015-07-17 + +### Changed +- BAM spec v3.0b7 compliance + - Removal of 'M' as allowed CIGAR operation. Attempt to use such a CIGAR op + will throw an exception. + - Addition of IPD/PulseWidth codec version info in header + +### Added +- Auto-generation of UTC timestamp for DataSet objects +- PbiBuilder - allows generation of PBI index data alongside generation or +modification of BAM record data. This obviates the need to wait for a completed +BAM, then go through the zlib decompression, etc. +- Added DataSet::FromXml(string xml) to create DataSets from "raw" XML string, +rather than building up using DataSet API or loading from existing file. +- "pbindex" command line tool to generate ".pbi" files from BAM data. The +executable is built by default, but can be disabled using the cmake option +"-DPacBioBAM_build_pbindex=OFF". + +### Fixed +- PBI construction failing on CCS reads + +## [0.0.8] - 2015-07-02 + +### Changed +- Build system refactoring. + +## [0.0.7] - 2015-07-02 + +### Added +- PBI index lookup API. Not so much intended for client use directly, but will +enable construction of higher-level semantic queries: grouping by, filtering, +etc. +- DataSet & PBI-aware queries (e.g. ZmwGroupQuery). More PBI-enabled queries to +follow. +- More flexibility in tag access. Samtools has a habit of performing a +"shrink-to-fit" when it handles integer-valued tag data. Thus we cannot +**guarantee** the binary type that our API will have to process. Safe +conversions are allowed on integer-like data only. Under- or overflows in +casting will trigger an exception. All other tag data types must be asked for +explicitly, or else an exception will be raised, as before. +- BamHeader::DeepCopy - allows creation of editable header data, without +overwriting all shared instances + +### Fixed +- XSD compliance for DataSet APIs. + +### Changed +- The functionality provided by ZmwQuery (group by hole number), is now +available using the ZmwGroupQuery object. The new ZmwQuery returns a single- +record iterator (a la EntireFileQuery), but limited to a whitelist of requested +hole numbers. + +### Removed +- XSD non-compliant classes (e.g. ExternalDataReference) + +## [0.0.6] - 2015-06-07 + +### Added + +- Accessor methods for pulse bam support: + - LabelQV() + - AltLabelQV() + - LabelTag() + - AltLabelTag() + - Pkmean() + - Pkmid() + - PrePulseFrames() only RC, no clipping + - PulseCallWidth() only RC, no clipping + - PulseCall() case-sensitive RC, no clipping + - IPDRaw() to avoid up and downscaling for stitching +- BamRecord::ParseTagName and BamRecord::ParseTagString to convert a two + character tag string to a TagName enum and back. Allows a switch over tags. +- VirtualPolymeraseReader to create VirtualPolymeraseBamRecord from a + subreads|hqregion+scraps.bam +- VirtualRegion represents annotations of the polymerase reads, for adapters, + barcodes, lqregions, and hqregions. +- ReadGroupInfo operator== + +### Fixed + +- Reimplemented QueryStart(int), QueryEnd(int), UpdateName(void), + ReadGroup(ReadGroupInfo&), ReadGroupId(std::string&); + +## [0.0.5] - 2015-05-29 + +### Added + +- DataSet support. This includes XML I/O, basic dataset query/manipulation, and +multi-BAM-file queries. New classes are located in . DataSet- +capable queries currently reside in the PacBio::BAM::staging namespace. These +will be ported over to the main namespace once the support is stabilized and +works seamlessly with either a single BamFile or DataSet object as input. (bug +25941) +- PBI support. This includes read/write raw data & building from a BamFile. The +lookup API for random-access queries is under development, but the raw data is +available - for creating PBI files & generating summary statistics. (bug 26025) +- C# SWIG bindings, alongside existing Python and R wrappers. +- LocalContextFlags support in BamRecord (bug 26623) + +### Fixed + +- BamRecord[Impl] map quality now initialized with 255 (missing) value, instead +of 0. (bug 26228) +- ReadGroupId calculation. (bug 25940) + +## [0.0.4] - 2015-04-22 + +### Added + +- This changelog. Hope it helps. +- Hook to set verbosity of underlying htslib warnings. +- Grouped queries. (bug 26361) + +### Changed + +- Now using exceptions instead of return codes, output parameters, etc. +- Removed "messy" shared_ptrs across interface (see especially BamHeader). These +are now taken care of within the API, not exposed to client code. + +### Removed + +- BamReader + +### Fixed + +- ASCII tag output. (bug 26381) diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..86dddda --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,3 @@ +# PacBio::BAM - building & integrating + +Detailed build instructions can be found [here](http://pbbam.readthedocs.org/en/latest/getting_started.html). diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..fc6affb --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,34 @@ +Copyright (c) 2014-2018, Pacific Biosciences of California, Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted (subject to the limitations in the +disclaimer below) provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Pacific Biosciences nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE +GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY PACIFIC +BIOSCIENCES AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL PACIFIC BIOSCIENCES OR ITS +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9db996 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# pbbam + +[![Build Status](https://travis-ci.org/PacificBiosciences/pbbam.svg?branch=master)](https://travis-ci.org/PacificBiosciences/pbbam) [![Documentation Status](https://readthedocs.org/projects/pbbam/badge/?version=latest)](http://pbbam.readthedocs.org/en/latest/?badge=latest) + +As of the 3.0 release of SMRTanalysis, PacBio is embracing the industry standard BAM +format for (both aligned and unaligned) basecall data files. We have also formulated +a BAM companion file format (bam.pbi) enabling fast access to a richer set of per-read +information as well as compatibility for software built around the legacy cmp.h5 format. + +The **pbbam** software package provides components to create, query, & edit PacBio BAM +files and associated indices. These components include a core C++ library, bindings for +additional languages, and command-line utilities. + +### Note: + +This library is **not** intended to be used as a general-purpose BAM utility - all input & output BAMs must adhere to the [PacBio BAM format specification](https://github.com/PacificBiosciences/PacBioFileFormats/blob/3.0/BAM.rst). Non-PacBio BAMs will cause exceptions to be thrown. + +## Documentation + + - [Documentation Home](http://pbbam.readthedocs.org/en/latest/index.html) + - [Getting Started](http://pbbam.readthedocs.org/en/latest/getting_started.html) + - [C++ API Reference](http://pbbam.readthedocs.org/en/latest/api_reference.html) + + - [Changelog](https://github.com/PacificBiosciences/pbbam/blob/master/CHANGELOG.md) + +## FAQ + +### [Help! I am getting "unsupported sequencing chemistry combination"!](#chemistry-bundle) + +**pbbam** validates all BAM files, and as part of this validation, it checks whether the +`BindingKit` and `SequencingKit` variables in every ReadGroup of the provided BAM file are +known. As part of ongoing chemistry developments, we might need to introduce new part numbers +to identify novel reagents and/or SMRT Cells. You are unlikely to encounter such issues +when using SMRT Link, as it has an integrated auto-updater that will periodically check and +install new chemistries automatically. All PacBio tools being used without a proper SMRT Link +installation will require manual intervention to download new chemistries: + + ```sh + cd + export SMRT_CHEMISTRY_BUNDLE_DIR="${PWD}" + + wget https://raw.githubusercontent.com/PacificBiosciences/pbcore/develop/pbcore/chemistry/resources/mapping.xml -O chemistry.xml + ``` + +This will cause **pbbam** to try to load the out-of-band `chemistry.xml` from +`SMRT_CHEMISTRY_BUNDLE_DIR` and should allow you to use somewhat older software +with somewhat newer BAMs. **Note:** this only allows **pbbam**'s internal validation +to pass, this will not automatically make other chemistry-dependent software work +with newer chemistries. For instance, Arrow's backend ([Unanimity](https://github.com/PacificBiosciences/unanimity)) +is parametrized on chemistry too, and it will fail should a completely new chemistry +be introduced. See Unanimity's FAQ on how to employ `SMRT_CHEMISTRY_BUNDLE_DIR` +to load models for new chemistries. + + +## License + + - [PacBio open source license](https://github.com/PacificBiosciences/pbbam/blob/master/LICENSE.txt) + +DISCLAIMER +---------- +THIS WEBSITE AND CONTENT AND ALL SITE-RELATED SERVICES, INCLUDING ANY DATA, ARE PROVIDED "AS IS," WITH ALL FAULTS, WITH NO REPRESENTATIONS OR WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, NON-INFRINGEMENT OR FITNESS FOR A PARTICULAR PURPOSE. YOU ASSUME TOTAL RESPONSIBILITY AND RISK FOR YOUR USE OF THIS SITE, ALL SITE-RELATED SERVICES, AND ANY THIRD PARTY WEBSITES OR APPLICATIONS. NO ORAL OR WRITTEN INFORMATION OR ADVICE SHALL CREATE A WARRANTY OF ANY KIND. ANY REFERENCES TO SPECIFIC PRODUCTS OR SERVICES ON THE WEBSITES DO NOT CONSTITUTE OR IMPLY A RECOMMENDATION OR ENDORSEMENT BY PACIFIC BIOSCIENCES. + diff --git a/bamboo_build.sh b/bamboo_build.sh new file mode 100755 index 0000000..7e01cf6 --- /dev/null +++ b/bamboo_build.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +set -vex + +################ +# DEPENDENCIES # +################ + +## Load modules +type module >& /dev/null || . /mnt/software/Modules/current/init/bash + +module purge + +module load meson +module load ninja + +module load zlib +module load htslib +module load samtools + +module load boost + +module load cram + + +export BUILD_NUMBER="0" +case "${bamboo_planRepository_branchName}" in + develop|master) + _install_image_default="${INSTALL_IMAGE:-false}" + _create_artifact_default="${CREATE_ARTIFACT:-false}" + + export PREFIX_ARG="/mnt/software/p/pbbam/${bamboo_planRepository_branchName}" + export BUILD_NUMBER="${bamboo_globalBuildNumber:-0}" + ;; +esac + +export _install_image="${_install_image_default:-false}" +export _create_artifact="${_create_artifact_default:-false}" + + +BOOST_ROOT="${BOOST_ROOT%/include}" +# unset these variables to have meson discover all +# boost-dependent variables from BOOST_ROOT alone +unset BOOST_INCLUDEDIR +unset BOOST_LIBRARYDIR + +# in order to make shared libraries consumable +# by conda and other package managers +export LDFLAGS=${LDFLAGS:-"-fuse-ld=gold -static-libstdc++ -static-libgcc"} + +source scripts/ci/setup.sh +source scripts/ci/build.sh +source scripts/ci/test.sh +source scripts/ci/install.sh +source scripts/ci/artifact.sh diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in new file mode 100644 index 0000000..90f6f63 --- /dev/null +++ b/docs/Doxyfile.in @@ -0,0 +1,1602 @@ +# Doxyfile 1.6.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PacBioBAM_NAME@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PacBioBAM_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @PacBioBAM_DocsDir@ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = @PacBioBAM_IncludeDir@ + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 1 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#samSpecURL=http://samtools.sourceforge.net/SAM1.pdf + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set +# FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @PacBioBAM_IncludeDir@ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = @PacBioBAM_IncludeDir@/pbbam/internal + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = pugi, PacBio::BAM::internal + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = examples + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = YES + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..14e0fb1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,168 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build +SOURCEDIR = source + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCEDIR) +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCEDIR) + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext fig + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: basefig MANY_CLUSTER.png + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pbtoolkits.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pbtoolkits.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/pbtoolkits" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pbtoolkits" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +basefig: + dot -Tpng $(SOURCEDIR)/dependencies.dot > $(SOURCEDIR)/$@ + grep -v "\"pbsmrtpipe\" ->" $(SOURCEDIR)/dependencies.dot \ + | grep -v "> \"pbcore\"" \ + | sed 's/All/Sparse/' > $(SOURCEDIR)/sparse_dependencies.dot + dot -Tpng $(SOURCEDIR)/sparse_dependencies.dot \ + > $(SOURCEDIR)/sparse_dependencies.png + +%.png: basefig + grep -v $* $(SOURCEDIR)/sparse_dependencies.dot | \ + grep -v \? | sed 's/Sparse dependencies/Module bundles/' | \ + dot -Tpng > $(SOURCEDIR)/$@ + diff --git a/docs/examples/code/BarcodeQuery.txt b/docs/examples/code/BarcodeQuery.txt new file mode 100644 index 0000000..3fe8fce --- /dev/null +++ b/docs/examples/code/BarcodeQuery.txt @@ -0,0 +1,17 @@ +// using C++11 range-based for loop +BarcodeQuery query(42, dataset); +for (const BamRecord& r : query) { + assert(r.HasBarcodes()); + assert(r.BarcodeForward() == 42 || r.barcodeReverse() == 42); +} + +// OR + +// using iterators directly +BarcodeQuery query(42, dataset); +auto iter = query.cbegin(); +auto end = query.cend(); +for (; iter != end; ++iter) { + assert(iter->HasBarcodes()); + assert(iter->BarcodeForward() == 42 || iter->barcodeReverse() == 42); +} diff --git a/docs/examples/code/Compare.txt b/docs/examples/code/Compare.txt new file mode 100644 index 0000000..deecd8d --- /dev/null +++ b/docs/examples/code/Compare.txt @@ -0,0 +1,3 @@ +// sort on increasing ZMW hole number +std::vector records; +std::sort(records.begin(), records.end(), Compare::Zmw()); diff --git a/docs/examples/code/Compare_AlignedEnd.txt b/docs/examples/code/Compare_AlignedEnd.txt new file mode 100644 index 0000000..d34ed67 --- /dev/null +++ b/docs/examples/code/Compare_AlignedEnd.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::AlignedEnd()); diff --git a/docs/examples/code/Compare_AlignedStart.txt b/docs/examples/code/Compare_AlignedStart.txt new file mode 100644 index 0000000..68de3e2 --- /dev/null +++ b/docs/examples/code/Compare_AlignedStart.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::AlignedStart()); diff --git a/docs/examples/code/Compare_AlignedStrand.txt b/docs/examples/code/Compare_AlignedStrand.txt new file mode 100644 index 0000000..6c22cdc --- /dev/null +++ b/docs/examples/code/Compare_AlignedStrand.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::AlignedStrand()); diff --git a/docs/examples/code/Compare_BarcodeForward.txt b/docs/examples/code/Compare_BarcodeForward.txt new file mode 100644 index 0000000..1967341 --- /dev/null +++ b/docs/examples/code/Compare_BarcodeForward.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::BarcodeForward()); diff --git a/docs/examples/code/Compare_BarcodeQuality.txt b/docs/examples/code/Compare_BarcodeQuality.txt new file mode 100644 index 0000000..144f483 --- /dev/null +++ b/docs/examples/code/Compare_BarcodeQuality.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::BarcodeQuality()); diff --git a/docs/examples/code/Compare_BarcodeReverse.txt b/docs/examples/code/Compare_BarcodeReverse.txt new file mode 100644 index 0000000..9d3b245 --- /dev/null +++ b/docs/examples/code/Compare_BarcodeReverse.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::BarcodeReverse()); diff --git a/docs/examples/code/Compare_FullName.txt b/docs/examples/code/Compare_FullName.txt new file mode 100644 index 0000000..4b392b9 --- /dev/null +++ b/docs/examples/code/Compare_FullName.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::FullName()); diff --git a/docs/examples/code/Compare_LocalContextFlag.txt b/docs/examples/code/Compare_LocalContextFlag.txt new file mode 100644 index 0000000..aeab944 --- /dev/null +++ b/docs/examples/code/Compare_LocalContextFlag.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::LocalContextFlag()); diff --git a/docs/examples/code/Compare_MapQuality.txt b/docs/examples/code/Compare_MapQuality.txt new file mode 100644 index 0000000..fe22821 --- /dev/null +++ b/docs/examples/code/Compare_MapQuality.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::MapQuality()); diff --git a/docs/examples/code/Compare_MovieName.txt b/docs/examples/code/Compare_MovieName.txt new file mode 100644 index 0000000..cddcb64 --- /dev/null +++ b/docs/examples/code/Compare_MovieName.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::MovieName()); diff --git a/docs/examples/code/Compare_NumDeletedBases.txt b/docs/examples/code/Compare_NumDeletedBases.txt new file mode 100644 index 0000000..aa6dd4b --- /dev/null +++ b/docs/examples/code/Compare_NumDeletedBases.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::NumDeletedBases()); diff --git a/docs/examples/code/Compare_NumInsertedBases.txt b/docs/examples/code/Compare_NumInsertedBases.txt new file mode 100644 index 0000000..917d87f --- /dev/null +++ b/docs/examples/code/Compare_NumInsertedBases.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::NumInsertedBases()); diff --git a/docs/examples/code/Compare_NumMatches.txt b/docs/examples/code/Compare_NumMatches.txt new file mode 100644 index 0000000..47e3081 --- /dev/null +++ b/docs/examples/code/Compare_NumMatches.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::NumMatches()); diff --git a/docs/examples/code/Compare_NumMismatches.txt b/docs/examples/code/Compare_NumMismatches.txt new file mode 100644 index 0000000..12affb1 --- /dev/null +++ b/docs/examples/code/Compare_NumMismatches.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::NumMismatches()); diff --git a/docs/examples/code/Compare_QueryEnd.txt b/docs/examples/code/Compare_QueryEnd.txt new file mode 100644 index 0000000..d664d28 --- /dev/null +++ b/docs/examples/code/Compare_QueryEnd.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::QueryEnd()); diff --git a/docs/examples/code/Compare_QueryStart.txt b/docs/examples/code/Compare_QueryStart.txt new file mode 100644 index 0000000..12f6244 --- /dev/null +++ b/docs/examples/code/Compare_QueryStart.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::QueryStart()); diff --git a/docs/examples/code/Compare_ReadAccuracy.txt b/docs/examples/code/Compare_ReadAccuracy.txt new file mode 100644 index 0000000..9454309 --- /dev/null +++ b/docs/examples/code/Compare_ReadAccuracy.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::ReadAccuracy()); diff --git a/docs/examples/code/Compare_ReadGroupId.txt b/docs/examples/code/Compare_ReadGroupId.txt new file mode 100644 index 0000000..dab3497 --- /dev/null +++ b/docs/examples/code/Compare_ReadGroupId.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::ReadGroupId()); diff --git a/docs/examples/code/Compare_ReadGroupNumericId.txt b/docs/examples/code/Compare_ReadGroupNumericId.txt new file mode 100644 index 0000000..5ad8f9d --- /dev/null +++ b/docs/examples/code/Compare_ReadGroupNumericId.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::ReadGroupNumericId()); diff --git a/docs/examples/code/Compare_ReferenceEnd.txt b/docs/examples/code/Compare_ReferenceEnd.txt new file mode 100644 index 0000000..ed42d05 --- /dev/null +++ b/docs/examples/code/Compare_ReferenceEnd.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::ReferenceEnd()); diff --git a/docs/examples/code/Compare_ReferenceId.txt b/docs/examples/code/Compare_ReferenceId.txt new file mode 100644 index 0000000..5628427 --- /dev/null +++ b/docs/examples/code/Compare_ReferenceId.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::ReferenceId()); diff --git a/docs/examples/code/Compare_ReferenceName.txt b/docs/examples/code/Compare_ReferenceName.txt new file mode 100644 index 0000000..1f76e7e --- /dev/null +++ b/docs/examples/code/Compare_ReferenceName.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::ReferenceName()); diff --git a/docs/examples/code/Compare_ReferenceStart.txt b/docs/examples/code/Compare_ReferenceStart.txt new file mode 100644 index 0000000..0ccaf36 --- /dev/null +++ b/docs/examples/code/Compare_ReferenceStart.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::ReferenceStart()); diff --git a/docs/examples/code/Compare_TypeFromOperator.txt b/docs/examples/code/Compare_TypeFromOperator.txt new file mode 100644 index 0000000..afb0848 --- /dev/null +++ b/docs/examples/code/Compare_TypeFromOperator.txt @@ -0,0 +1,2 @@ +Compare::Type type = Compare::TypeFromOperator("!="); +assert(type == Compare::NOT_EQUAL); diff --git a/docs/examples/code/Compare_TypeToName.txt b/docs/examples/code/Compare_TypeToName.txt new file mode 100644 index 0000000..c44e1cb --- /dev/null +++ b/docs/examples/code/Compare_TypeToName.txt @@ -0,0 +1,2 @@ +string name = Compare::TypeToName(Compare::LESS_THAN); +assert(name = "Compare::LESS_THAN"); diff --git a/docs/examples/code/Compare_Zmw.txt b/docs/examples/code/Compare_Zmw.txt new file mode 100644 index 0000000..b02c426 --- /dev/null +++ b/docs/examples/code/Compare_Zmw.txt @@ -0,0 +1,2 @@ +std::vector records; +std::sort(records.begin(), records.end(), Compare::Zmw()); diff --git a/docs/examples/code/EntireFileQuery.txt b/docs/examples/code/EntireFileQuery.txt new file mode 100644 index 0000000..d3fcc2c --- /dev/null +++ b/docs/examples/code/EntireFileQuery.txt @@ -0,0 +1,15 @@ +// using C++11 range-based for loop +EntireFileQuery query(dataset); +for (const BamRecord& record : query) { + // ... do stuff ... +} + +// OR + +// using iterators +EntireFileQuery query(dataset); +auto iter = query.cbegin(); +auto end = query.cend(); +for (; iter != end; ++iter) { + // ... do stuff ... +} diff --git a/docs/examples/code/EntireFileQuery_BamFilename.txt b/docs/examples/code/EntireFileQuery_BamFilename.txt new file mode 100644 index 0000000..484db61 --- /dev/null +++ b/docs/examples/code/EntireFileQuery_BamFilename.txt @@ -0,0 +1,4 @@ +EntireFileQuery query("foo.bam"); +for (const BamRecord& record : query) { + // do stuff +} diff --git a/docs/examples/code/EntireFileQuery_NonConst.txt b/docs/examples/code/EntireFileQuery_NonConst.txt new file mode 100644 index 0000000..a0a092e --- /dev/null +++ b/docs/examples/code/EntireFileQuery_NonConst.txt @@ -0,0 +1,4 @@ +EntireFileQuery query("foo.bam"); +for (BamRecord& record : query) { + // ok to modify 'record' here +} diff --git a/docs/examples/code/GenomicIntervalQuery.txt b/docs/examples/code/GenomicIntervalQuery.txt new file mode 100644 index 0000000..651f254 --- /dev/null +++ b/docs/examples/code/GenomicIntervalQuery.txt @@ -0,0 +1,16 @@ +// using C++11 range-based for loop +GenomicIntervalQuery query(GenomicInterval("chr1:1000-2000"), dataset); +for (const BamRecord& record : query) { + // ... do stuff ... +} + +// OR + +// using iterators directly +GenomicIntervalQuery query(GenomicInterval("chr1:1000-2000"), dataset); +auto iter = query.cbegin(); +auto end = query.cend(); +for (; iter != end; ++iter) { + // ... do stuff ... +} + diff --git a/docs/examples/code/GenomicIntervalQuery_Reuse.txt b/docs/examples/code/GenomicIntervalQuery_Reuse.txt new file mode 100644 index 0000000..339ae95 --- /dev/null +++ b/docs/examples/code/GenomicIntervalQuery_Reuse.txt @@ -0,0 +1,8 @@ +DataSet ds("data.xml"); +GenomicIntervalQuery query(GenomicInterval(), ds); +for (const GenomicInterval& interval : intervals) { + query.Interval(interval); + for (const BamRecord& record : query) {} + // do stuff + } +} \ No newline at end of file diff --git a/docs/examples/code/PbiAlignedEndFilter.txt b/docs/examples/code/PbiAlignedEndFilter.txt new file mode 100644 index 0000000..bac1a46 --- /dev/null +++ b/docs/examples/code/PbiAlignedEndFilter.txt @@ -0,0 +1,4 @@ +PbiFilterQuery query(PbiAlignedEndFilter{3000, Compare::GREATER_THAN}); +for (const BamRecord& record : query) { + assert(record.AlignedEnd() > 3000); +} diff --git a/docs/examples/code/PbiAlignedLengthFilter.txt b/docs/examples/code/PbiAlignedLengthFilter.txt new file mode 100644 index 0000000..38dc3ff --- /dev/null +++ b/docs/examples/code/PbiAlignedLengthFilter.txt @@ -0,0 +1,4 @@ +PbiFilterQuery query(PbiAlignedLengthFilter{1000, Compare::GREATER_THAN}); +for (const BamRecord& record : query) { + assert((record.AlignedEnd() - record.AlignedStart()) > 1000); +} diff --git a/docs/examples/code/PbiAlignedStartFilter.txt b/docs/examples/code/PbiAlignedStartFilter.txt new file mode 100644 index 0000000..b78bb2c --- /dev/null +++ b/docs/examples/code/PbiAlignedStartFilter.txt @@ -0,0 +1,4 @@ +PbiFilterQuery query(PbiAlignedStartFilter{3000, Compare::GREATER_THAN}); +for (const BamRecord& record : query) { + assert(record.AlignedStart() > 3000); +} diff --git a/docs/examples/code/PbiAlignedStrandFilter.txt b/docs/examples/code/PbiAlignedStrandFilter.txt new file mode 100644 index 0000000..9f9a885 --- /dev/null +++ b/docs/examples/code/PbiAlignedStrandFilter.txt @@ -0,0 +1,5 @@ +PbiFilterQuery query(PbiAlignedStrandFilter{Strand::FORWARD}); +for (const BamRecord& record : query) { + assert(record.AlignedStrand() == Strand::FORWARD); +} + diff --git a/docs/examples/code/PbiBarcodeFilter.txt b/docs/examples/code/PbiBarcodeFilter.txt new file mode 100644 index 0000000..c7ce5cb --- /dev/null +++ b/docs/examples/code/PbiBarcodeFilter.txt @@ -0,0 +1,17 @@ +// single value +PbiFilter filter{ PbiBarcodeFilter{17} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + const auto barcodes = record.Barcodes(); + assert(barcodes.first == 17 || barcodes.second == 17); +} + +// whitelist +vector whitelist = { 50, 100 }; +PbiFilter filter{ PbiBarcodeFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + const auto barcodes = record.Barcodes(); + assert(barcodes.first == 50 || barcodes.second == 50 || + barcodes.first == 100 || barcodes.second == 100); +} diff --git a/docs/examples/code/PbiBarcodeForwardFilter.txt b/docs/examples/code/PbiBarcodeForwardFilter.txt new file mode 100644 index 0000000..a6c12fd --- /dev/null +++ b/docs/examples/code/PbiBarcodeForwardFilter.txt @@ -0,0 +1,15 @@ +// single value +PbiFilter filter{ PbiBarcodeForwardFilter{50} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.BarcodeForward() == 50); +} + +// whitelist +vector whitelist = { 50, 100 }; +PbiFilter filter{ PbiBarcodeForwardFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.BarcodeForward() == 50 || record.BarcodeForward() == 100); +} + diff --git a/docs/examples/code/PbiBarcodeQualityFilter.txt b/docs/examples/code/PbiBarcodeQualityFilter.txt new file mode 100644 index 0000000..34311d0 --- /dev/null +++ b/docs/examples/code/PbiBarcodeQualityFilter.txt @@ -0,0 +1,5 @@ +PbiFilter filter{ PbiBarcodeQualityFilter{42, Compare::GREATER_THAN_EQUAL} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.BarcodeQuality() >= 42); +} diff --git a/docs/examples/code/PbiBarcodeReverseFilter.txt b/docs/examples/code/PbiBarcodeReverseFilter.txt new file mode 100644 index 0000000..24134f8 --- /dev/null +++ b/docs/examples/code/PbiBarcodeReverseFilter.txt @@ -0,0 +1,15 @@ +// single value +PbiFilter filter{ PbiBarcodeReverseFilter{50} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.BarcodeReverse() == 50); +} + +// whitelist +vector whitelist = { 50, 100 }; +PbiFilter filter{ PbiBarcodeReverseFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.BarcodeReverse() == 50 || record.BarcodeReverse() == 100); +} + diff --git a/docs/examples/code/PbiBarcodesFilter.txt b/docs/examples/code/PbiBarcodesFilter.txt new file mode 100644 index 0000000..a655c57 --- /dev/null +++ b/docs/examples/code/PbiBarcodesFilter.txt @@ -0,0 +1,6 @@ +PbiFilter filter{ PbiBarcodesFilter{17, 18} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.BarcodeForward() == 17 && + record.BarcodeReverse() == 18); +} diff --git a/docs/examples/code/PbiBuilder_WithReader.txt b/docs/examples/code/PbiBuilder_WithReader.txt new file mode 100644 index 0000000..e2748c2 --- /dev/null +++ b/docs/examples/code/PbiBuilder_WithReader.txt @@ -0,0 +1,30 @@ +// To simply create a PBI file from BAM, the following is the easiest method: +// +#include +#include + +BamFile bamFile("data.bam"); +PbiFile::CreateFrom(bamFile); + + +// However if you need to perform additional operations while reading the BAM file, +// you can do something like the following: +// +{ + BamFile bamFile("data.bam"); + PbiBuilder builder(bamFile.PacBioIndexFilename(), + bamFile.Header().Sequences().size()); + BamReader reader(bamFile); + BamRecord b; + int64_t offset = reader.VirtualTell(); // first record's vOffset + while (reader.GetNext(b)) { + + // store PBI recrod entry & get next record's vOffset + builder.AddRecord(b, offset); + offset = reader.VirtualTell(); + + // ... additional stuff as needed ... + } + +} // <-- PBI data will only be written here, as PbiBuilder goes out of scope + diff --git a/docs/examples/code/PbiBuilder_WithWriter.txt b/docs/examples/code/PbiBuilder_WithWriter.txt new file mode 100644 index 0000000..0c7d6d1 --- /dev/null +++ b/docs/examples/code/PbiBuilder_WithWriter.txt @@ -0,0 +1,12 @@ +BamWriter writer(...); +PbiBuilder pbiBuilder(...); +int64_t vOffset; +BamRecord record; +while (...) { + + // ... populate record data ... + + // write record to BAM and add PBI entry + writer.Write(record, &vOffset); + pbiBuilder.AddRecord(record, vOffset); +} diff --git a/docs/examples/code/PbiFilterQuery.txt b/docs/examples/code/PbiFilterQuery.txt new file mode 100644 index 0000000..4914eab --- /dev/null +++ b/docs/examples/code/PbiFilterQuery.txt @@ -0,0 +1,22 @@ +// setup filter +PbiFilter filter; +filter.Add(PbiZmwFilter(42)); +filter.Add(PbiReadAccuracyFilter(0.9, Compare::GREATER_THAN_EQUAL)); + +// using C++11 range-based for loop +PbiFilterQuery query(filter, dataset); +for (const BamRecord& r : query) { + assert(r.HoleNumber() == 42); + assert(r.ReadAccuracy() >= 0.9); +} + +// OR + +// using iterators directly +PbiFilterQuery query(filter, dataset); +auto iter = query.cbegin(); +auto end = query.cend(); +for (; iter != end; ++iter) { + assert(iter->HoleNumber() == 42); + assert(iter->ReadAccuracy() >= 0.9); +} diff --git a/docs/examples/code/PbiFilter_Composition.txt b/docs/examples/code/PbiFilter_Composition.txt new file mode 100644 index 0000000..22cc6ff --- /dev/null +++ b/docs/examples/code/PbiFilter_Composition.txt @@ -0,0 +1,8 @@ +// (f1 && f2) || f3 + +PbiFilter f1; +PbiFilter f2; +PbiFilter intersect_f1_f2 = PbiFilter::Intersection(f1, f2); + +PbiFilter f3; +PbiFilter final = PbiFilter::Union(intersect_f1_f2, f3); diff --git a/docs/examples/code/PbiFilter_CustomFilter.txt b/docs/examples/code/PbiFilter_CustomFilter.txt new file mode 100644 index 0000000..f9cdd21 --- /dev/null +++ b/docs/examples/code/PbiFilter_CustomFilter.txt @@ -0,0 +1,21 @@ +struct MyCustomFilter +{ + bool Accepts(const PbiRawData& index, const size_t row) const + { + // Look up data for record at the provided row. Do any calculations + // necessary, then return whether that record passes your + // filter criteria. + + return true; + } +}; + +// use in composite filters +PbiFilter f; +f.Add(PbiMovieNameFilter("foo")); +f.Add(MyCustomFilter()); + +// pass directly to PbiFilterQuery +PbiFilterQuery query(MyCustomFilter(), "foo.bam"); +for (const BamRecord& record : query) + // ... do stuff ... diff --git a/docs/examples/code/PbiFilter_Interface.txt b/docs/examples/code/PbiFilter_Interface.txt new file mode 100644 index 0000000..0fea900 --- /dev/null +++ b/docs/examples/code/PbiFilter_Interface.txt @@ -0,0 +1 @@ +bool Accepts(const PbiRawData& index, const size_t row) const; diff --git a/docs/examples/code/PbiIdentityFilter.txt b/docs/examples/code/PbiIdentityFilter.txt new file mode 100644 index 0000000..6fcb8d0 --- /dev/null +++ b/docs/examples/code/PbiIdentityFilter.txt @@ -0,0 +1,6 @@ +// single value +PbiFilter filter{ PbiIdentityFilter{ 0.5, Compare::GREATER_THAN_EQUAL } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + // ... at least 50% of record was aligned ... +} diff --git a/docs/examples/code/PbiLocalContextFilter.txt b/docs/examples/code/PbiLocalContextFilter.txt new file mode 100644 index 0000000..0aaa3eb --- /dev/null +++ b/docs/examples/code/PbiLocalContextFilter.txt @@ -0,0 +1,22 @@ + +// -------------------- +// has adapter_before +// -------------------- + +PbiFilter filter{ PbiLocalContextFilter{LocalContextFlags::ADAPTER_BEFORE, Compare::CONTAINS} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + const bool hasAdapterBefore = (record.LocalContextFlags() & LocalContextFlags::ADAPTER_BEFORE) != 0; + assert(hasAdapterBefore); +} + +// ---------------------------------- +// has any adapters, barcodes, etc. +// ---------------------------------- + +PbiFilter filter{ PbiLocalContextFilter{LocalContextFlags::NO_LOCAL_CONTEXT, Compare::NOT_EQUAL} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + const bool hasContext = (record.LocalContextFlags() != LocalContextFlags::NO_LOCAL_CONTEXT); + assert(hasContext); +} diff --git a/docs/examples/code/PbiMapQualityFilter.txt b/docs/examples/code/PbiMapQualityFilter.txt new file mode 100644 index 0000000..67fb5dc --- /dev/null +++ b/docs/examples/code/PbiMapQualityFilter.txt @@ -0,0 +1,5 @@ +PbiFilter filter{ PbiMapQualityFilter{75, Compare::GREATER_THAN_EQUAL} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.MapQuality() >= 75); +} diff --git a/docs/examples/code/PbiMovieNameFilter.txt b/docs/examples/code/PbiMovieNameFilter.txt new file mode 100644 index 0000000..dd124e2 --- /dev/null +++ b/docs/examples/code/PbiMovieNameFilter.txt @@ -0,0 +1,14 @@ +// single value +PbiFilter filter{ PbiMovieFilter{ "foo" } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.MovieName() == "foo"); +} + +// whitelist +vector whitelist = { "foo", "bar" }; +PbiFilter filter{ PbiMovieNameFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.MovieName() == "foo" || record.MovieName() == "bar"); +} diff --git a/docs/examples/code/PbiNumDeletedBasesFilter.txt b/docs/examples/code/PbiNumDeletedBasesFilter.txt new file mode 100644 index 0000000..e1e3d1f --- /dev/null +++ b/docs/examples/code/PbiNumDeletedBasesFilter.txt @@ -0,0 +1,6 @@ +PbiFilter filter{ PbiNumDeletedBasesFilter{50, Compare::LESS_THAN} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.NumDeletedBases() < 50); +} + diff --git a/docs/examples/code/PbiNumInsertedBasesFilter.txt b/docs/examples/code/PbiNumInsertedBasesFilter.txt new file mode 100644 index 0000000..ab385e4 --- /dev/null +++ b/docs/examples/code/PbiNumInsertedBasesFilter.txt @@ -0,0 +1,6 @@ +PbiFilter filter{ PbiNumInsertedBasesFilter{50, Compare::LESS_THAN} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.NumInsertedBases() < 50); +} + diff --git a/docs/examples/code/PbiNumMatchesFilter.txt b/docs/examples/code/PbiNumMatchesFilter.txt new file mode 100644 index 0000000..4e1b97d --- /dev/null +++ b/docs/examples/code/PbiNumMatchesFilter.txt @@ -0,0 +1,6 @@ +PbiFilter filter{ PbiNumMatchesFilter{2000, Compare::GREATER_THAN_EQUAL} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.NumMatches() >= 2000); +} + diff --git a/docs/examples/code/PbiNumMismatchesFilter.txt b/docs/examples/code/PbiNumMismatchesFilter.txt new file mode 100644 index 0000000..690e4a1 --- /dev/null +++ b/docs/examples/code/PbiNumMismatchesFilter.txt @@ -0,0 +1,6 @@ +PbiFilter filter{ PbiNumMismatchesFilter{500, Compare::LESS_THAN} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.NumMismatches() < 500); +} + diff --git a/docs/examples/code/PbiQueryEndFilter.txt b/docs/examples/code/PbiQueryEndFilter.txt new file mode 100644 index 0000000..f85166b --- /dev/null +++ b/docs/examples/code/PbiQueryEndFilter.txt @@ -0,0 +1,5 @@ +PbiFilter filter{ PbiQueryEndFilter{3000, Compare::GREATER_THAN} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.QueryEnd() > 3000); +} diff --git a/docs/examples/code/PbiQueryLengthFilter.txt b/docs/examples/code/PbiQueryLengthFilter.txt new file mode 100644 index 0000000..123412a --- /dev/null +++ b/docs/examples/code/PbiQueryLengthFilter.txt @@ -0,0 +1,5 @@ +PbiFilter filter{ PbiQueryLengthFilter{2000, Compare::GREATER_THAN} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert( (record.QueryEnd() - record.QueryStart()) > 2000 ); +} diff --git a/docs/examples/code/PbiQueryNameFilter.txt b/docs/examples/code/PbiQueryNameFilter.txt new file mode 100644 index 0000000..f1e51c7 --- /dev/null +++ b/docs/examples/code/PbiQueryNameFilter.txt @@ -0,0 +1,15 @@ +// single value +PbiFilter filter{ PbiQueryNameFilter{ "movie_1/42/100_200" } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.FullName() == "movie_1/42/100_200"); +} + +// whitelist +vector whitelist = { "movie_1/42/100_200", "movie_3/24/300_500" }; +PbiFilter filter{ PbiQueryNameFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.FullName() == "movie_1/42/100_200" || + record.FullName() == "movie_3/24/300_500"); +} diff --git a/docs/examples/code/PbiQueryStartFilter.txt b/docs/examples/code/PbiQueryStartFilter.txt new file mode 100644 index 0000000..56353df --- /dev/null +++ b/docs/examples/code/PbiQueryStartFilter.txt @@ -0,0 +1,5 @@ +PbiFilter filter{ PbiQueryStartFilter{3000, Compare::GREATER_THAN} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.QueryStart() > 3000); +} diff --git a/docs/examples/code/PbiReadAccuracyFilter.txt b/docs/examples/code/PbiReadAccuracyFilter.txt new file mode 100644 index 0000000..dd2df32 --- /dev/null +++ b/docs/examples/code/PbiReadAccuracyFilter.txt @@ -0,0 +1,5 @@ +PbiFilter filter{ PbiReadAccuracyFilter{0.8, Compare::GREATER_THAN_EQUAL} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReadAccuracy() >= 0.8); +} diff --git a/docs/examples/code/PbiReadGroupFilter.txt b/docs/examples/code/PbiReadGroupFilter.txt new file mode 100644 index 0000000..9af096d --- /dev/null +++ b/docs/examples/code/PbiReadGroupFilter.txt @@ -0,0 +1,64 @@ +// ------------------------- +// numeric ID +// ------------------------- + +// single value +PbiFilter filter{ PbiReadGroupFilter{ 2458765 } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReadGroupNumericId() == 2458765); +} + +// whitelist +vector whitelist = { 2458765, -32143 }; +PbiFilter filter{ PbiReadGroupFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReadGroupNumericId() == 2458765 || + record.ReadGroupNumericId() == -32143); +} + +// ------------------------- +// printable ID +// ------------------------- + +// single value +PbiFilter filter{ PbiReadGroupFilter{ "12B33F00" } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReadGroupId() == "12B33F00"); +} + +// whitelist +vector whitelist = { "12B33F00", "123ABC77" }; +PbiFilter filter{ PbiReadGroupFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReadGroupId() == "12B33F00" || + record.ReadGroupId() == "123ABC77"); +} + + +// ------------------------- +// read group +// ------------------------- + +BamFile file("foo.bam"); +BamHeader header = file.Header(); +assert(header.ReadGroups().size() > 1); + +// single value +PbiFilter filter{ PbiReadGroupFilter{ header.ReadGroups()[0] } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReadGroup() == header.ReadGroups()[0]); +} + +// whitelist +vector whitelist = { header.ReadGroups()[0], header.ReadGroups()[1] }; +PbiFilter filter{ PbiReadGroupFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReadGroup() == header.ReadGroups()[0] || + record.ReadGroup() == header.ReadGroups()[1]); +} diff --git a/docs/examples/code/PbiReferenceEndFilter.txt b/docs/examples/code/PbiReferenceEndFilter.txt new file mode 100644 index 0000000..ce005c6 --- /dev/null +++ b/docs/examples/code/PbiReferenceEndFilter.txt @@ -0,0 +1,5 @@ +PbiFilter filter{ PbiReferenceEndFilter{ 2000 } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReferenceEnd() == 2000); +} diff --git a/docs/examples/code/PbiReferenceIdFilter.txt b/docs/examples/code/PbiReferenceIdFilter.txt new file mode 100644 index 0000000..d963d28 --- /dev/null +++ b/docs/examples/code/PbiReferenceIdFilter.txt @@ -0,0 +1,16 @@ +// single value +PbiFilter filter{ PbiReferenceIdFilter{ 4 } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReferenceId() == 4); +} + +// whitelist +vector whitelist = { 0, 1 }; +PbiFilter filter{ PbiReferenceIdFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReferenceId() == 0 || + record.ReferenceId() == 1); +} + diff --git a/docs/examples/code/PbiReferenceNameFilter.txt b/docs/examples/code/PbiReferenceNameFilter.txt new file mode 100644 index 0000000..c86b14a --- /dev/null +++ b/docs/examples/code/PbiReferenceNameFilter.txt @@ -0,0 +1,15 @@ +// single value +PbiFilter filter{ PbiReferenceNameFilter{ "chr1" } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReferenceName() == "chr1"); +} + +// whitelist +vector whitelist = { "chr1", "chr5" }; +PbiFilter filter{ PbiReferenceNameFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReferenceName() == "chr1" || + record.ReferenceName() == "chr5"); +} diff --git a/docs/examples/code/PbiReferenceStartFilter.txt b/docs/examples/code/PbiReferenceStartFilter.txt new file mode 100644 index 0000000..d3ffdbb --- /dev/null +++ b/docs/examples/code/PbiReferenceStartFilter.txt @@ -0,0 +1,5 @@ +PbiFilter filter{ PbiReferenceStartFilter{ 2000 } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.ReferenceStart() == 2000); +} diff --git a/docs/examples/code/PbiZmwFilter.txt b/docs/examples/code/PbiZmwFilter.txt new file mode 100644 index 0000000..c63a804 --- /dev/null +++ b/docs/examples/code/PbiZmwFilter.txt @@ -0,0 +1,16 @@ +// single value +PbiFilter filter{ PbiZmwFilter{ 4000 } }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.HoleNumber() == 4000); +} + +// whitelist +vector whitelist = { 4000, 8000 }; +PbiFilter filter{ PbiZmwFilter{whitelist} }; +PbiFilterQuery query(filter); +for (const BamRecord& record : query) { + assert(record.HoleNumber() == 4000 || + record.HoleNumber() == 8000); +} + diff --git a/docs/examples/code/ReadAccuracyQuery.txt b/docs/examples/code/ReadAccuracyQuery.txt new file mode 100644 index 0000000..5b0404f --- /dev/null +++ b/docs/examples/code/ReadAccuracyQuery.txt @@ -0,0 +1,15 @@ +// using C++11 range-based for loop +ReadAccuracyQuery query(0.9, Compare::GREATER_THAN_EQUAL, dataset); +for (const BamRecord& r : query) { + assert(r.ReadAccuracy() >= 0.9); +} + +// OR + +// using iterators directly +ReadAccuracyQuery query(0.9, Compare::GREATER_THAN_EQUAL, dataset); +auto iter = query.cbegin(); +auto end = query.cend(); +for (; iter != end; ++iter) { + assert(iter->ReadAccuracy() >= 0.9); +} diff --git a/docs/examples/code/SubreadLengthQuery.txt b/docs/examples/code/SubreadLengthQuery.txt new file mode 100644 index 0000000..466a1d9 --- /dev/null +++ b/docs/examples/code/SubreadLengthQuery.txt @@ -0,0 +1,15 @@ +// using C++11 range-based for loop +SubreadLengthQuery query(500, Compare::GREATER_THAN_EQUAL, dataset); +for (const BamRecord& r : query) { + assert((r.QueryEnd() - r.QueryStart()) >= 500); +} + +// OR + +// using iterators directly +SubreadLengthQuery query(500, Compare::GREATER_THAN_EQUAL, dataset); +auto iter = query.cbegin(); +auto end = query.cend(); +for (; iter != end; ++iter) { + assert((iter->QueryEnd() - iter->QueryStart()) >= 500); +} diff --git a/docs/examples/code/Tag_AsciiCtor.txt b/docs/examples/code/Tag_AsciiCtor.txt new file mode 100644 index 0000000..057d22f --- /dev/null +++ b/docs/examples/code/Tag_AsciiCtor.txt @@ -0,0 +1,10 @@ +// One-step construction +// +// This is useful in situations that require a const Tag. +// +const auto t = Tag('A', TagModifier::ASCII_CHAR); + +// or two-step construction +auto t = Tag('A'); +t.Modifier(TagModifier::ASCII_CHAR); + diff --git a/docs/examples/code/WhitelistedZmwReadStitcher.txt b/docs/examples/code/WhitelistedZmwReadStitcher.txt new file mode 100644 index 0000000..a94c27b --- /dev/null +++ b/docs/examples/code/WhitelistedZmwReadStitcher.txt @@ -0,0 +1,6 @@ +vector zmws = { ... }; +WhitelistedZmwReadStitcher reader(zmws, "primary.bam", "scraps.bam"); +while(reader.HasNext()) { + auto virtualRecord = reader.Next(); + // ... do stuff ... +} diff --git a/docs/examples/code/ZmwGroupQuery.txt b/docs/examples/code/ZmwGroupQuery.txt new file mode 100644 index 0000000..1d728ac --- /dev/null +++ b/docs/examples/code/ZmwGroupQuery.txt @@ -0,0 +1,23 @@ +bool allHoleNumbersEqual(const vector& group) +{ + if (group.empty()) + return true; + const auto firstHoleNumber = group[0].HoleNumber(); + for (size_t i = 1; i < group.size(); ++i) { + if (group[i].HoleNumber() != firstHoleNumber) + return false; + } + return true; +} + +vector whitelist = { 50, 100 }; +ZmwGroupQuery query(whitelist, dataset); +for(const vector& group : query) { + + assert(allHoleNumbersEqual(group)); + + for (const BamRecord& record : group) { + assert(record.HoleNumber() == 50 || + record.HoleNumber() == 100); + } +} diff --git a/docs/examples/code/ZmwQuery.txt b/docs/examples/code/ZmwQuery.txt new file mode 100644 index 0000000..59c22c4 --- /dev/null +++ b/docs/examples/code/ZmwQuery.txt @@ -0,0 +1,6 @@ +vector whitelist = { 50, 100 }; +ZmwQuery query(whitelist, dataset); +for (const BamRecord& record : query) { + assert(record.HoleNumber() == 50 || + record.HoleNumber() == 100); +} diff --git a/docs/examples/plaintext/AlignmentPrinterOutput.txt b/docs/examples/plaintext/AlignmentPrinterOutput.txt new file mode 100644 index 0000000..21d948b --- /dev/null +++ b/docs/examples/plaintext/AlignmentPrinterOutput.txt @@ -0,0 +1,13 @@ +Read : singleInsertion2 +Reference : lambda_NEB3011 + +Read-length : 49 +Concordance : 0.96 + +5210 : GGCTGCAGTGTACAGCGGTCAGGAGGCC-ATTGATGCCGG : 5249 + |||||||| ||||||||||||||||||| ||||||||||| + 0 : GGCTGCAG-GTACAGCGGTCAGGAGGCCAATTGATGCCGG : 39 + +5249 : ACTGGCTGAT : 5259 + |||||||||| + 39 : ACTGGCTGAT : 49 diff --git a/docs/examples/plaintext/PbiFilter_DataSetXmlFilters.txt b/docs/examples/plaintext/PbiFilter_DataSetXmlFilters.txt new file mode 100644 index 0000000..5b5e8c2 --- /dev/null +++ b/docs/examples/plaintext/PbiFilter_DataSetXmlFilters.txt @@ -0,0 +1,14 @@ + + + + # A + # B + + + + + # C + # D + + + diff --git a/docs/meson.build b/docs/meson.build new file mode 100644 index 0000000..cffad5c --- /dev/null +++ b/docs/meson.build @@ -0,0 +1,24 @@ +################# +# documentation # +################# + +doxygen = find_program('doxygen', required : true) + +pbbam_doxygen_config = configuration_data() +pbbam_doxygen_config.set('PacBioBAM_NAME', meson.project_name()) +pbbam_doxygen_config.set('PacBioBAM_VERSION', meson.project_version()) +pbbam_doxygen_config.set('PacBioBAM_DocsDir', '.') +pbbam_doxygen_config.set('PacBioBAM_IncludeDir', join_paths([meson.current_source_dir(), '../include'])) + +doxyfile = configure_file( + input : 'Doxyfile.in', + output : 'Doxyfile', + configuration : pbbam_doxygen_config, + install : false) + +custom_target('docs', + input : doxyfile, + output : 'docs', + command : [doxygen, doxyfile], + build_by_default : true, + install : false) diff --git a/docs/source/api/Accuracy.rst b/docs/source/api/Accuracy.rst new file mode 100644 index 0000000..f88b722 --- /dev/null +++ b/docs/source/api/Accuracy.rst @@ -0,0 +1,11 @@ +Accuracy +======== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::Accuracy + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/AlignmentPrinter.rst b/docs/source/api/AlignmentPrinter.rst new file mode 100644 index 0000000..ef0b191 --- /dev/null +++ b/docs/source/api/AlignmentPrinter.rst @@ -0,0 +1,11 @@ +AlignmentPrinter +================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::AlignmentPrinter + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/AlignmentSet.rst b/docs/source/api/AlignmentSet.rst new file mode 100644 index 0000000..1817962 --- /dev/null +++ b/docs/source/api/AlignmentSet.rst @@ -0,0 +1,11 @@ +AlignmentSet +============ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::AlignmentSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BaiIndexedBamReader.rst b/docs/source/api/BaiIndexedBamReader.rst new file mode 100644 index 0000000..aab136f --- /dev/null +++ b/docs/source/api/BaiIndexedBamReader.rst @@ -0,0 +1,11 @@ +BaiIndexedBamReader +=================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BaiIndexedBamReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BamFile.rst b/docs/source/api/BamFile.rst new file mode 100644 index 0000000..c7e48fb --- /dev/null +++ b/docs/source/api/BamFile.rst @@ -0,0 +1,11 @@ +BamFile +======= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BamFile + :members: + :protected-members: + :undoc-members: diff --git a/docs/source/api/BamHeader.rst b/docs/source/api/BamHeader.rst new file mode 100644 index 0000000..6cf06af --- /dev/null +++ b/docs/source/api/BamHeader.rst @@ -0,0 +1,11 @@ +BamHeader +========= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BamHeader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BamReader.rst b/docs/source/api/BamReader.rst new file mode 100644 index 0000000..e0b6f3c --- /dev/null +++ b/docs/source/api/BamReader.rst @@ -0,0 +1,11 @@ +BamReader +========= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BamReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BamRecord.rst b/docs/source/api/BamRecord.rst new file mode 100644 index 0000000..a749775 --- /dev/null +++ b/docs/source/api/BamRecord.rst @@ -0,0 +1,17 @@ +BamRecord +========= + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::ClipType + +.. doxygenenum:: PacBio::BAM::RecordType + +.. doxygenenum:: PacBio::BAM::FrameEncodingType + +.. doxygenclass:: PacBio::BAM::BamRecord + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BamRecordBuilder.rst b/docs/source/api/BamRecordBuilder.rst new file mode 100644 index 0000000..ce477b4 --- /dev/null +++ b/docs/source/api/BamRecordBuilder.rst @@ -0,0 +1,11 @@ +BamRecordBuilder +================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BamRecordBuilder + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BamRecordImpl.rst b/docs/source/api/BamRecordImpl.rst new file mode 100644 index 0000000..92b6759 --- /dev/null +++ b/docs/source/api/BamRecordImpl.rst @@ -0,0 +1,11 @@ +BamRecordImpl +============= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BamRecordImpl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BamRecordView.rst b/docs/source/api/BamRecordView.rst new file mode 100644 index 0000000..2bc8fc4 --- /dev/null +++ b/docs/source/api/BamRecordView.rst @@ -0,0 +1,11 @@ +BamRecordView +============= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BamRecordView + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BamTagCodec.rst b/docs/source/api/BamTagCodec.rst new file mode 100644 index 0000000..9307421 --- /dev/null +++ b/docs/source/api/BamTagCodec.rst @@ -0,0 +1,11 @@ +BamTagCodec +=========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BamTagCodec + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BamWriter.rst b/docs/source/api/BamWriter.rst new file mode 100644 index 0000000..2e2951b --- /dev/null +++ b/docs/source/api/BamWriter.rst @@ -0,0 +1,11 @@ +BamWriter +========= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BamWriter + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BarcodeQuery.rst b/docs/source/api/BarcodeQuery.rst new file mode 100644 index 0000000..5836059 --- /dev/null +++ b/docs/source/api/BarcodeQuery.rst @@ -0,0 +1,11 @@ +BarcodeQuery +============ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BarcodeQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/BarcodeSet.rst b/docs/source/api/BarcodeSet.rst new file mode 100644 index 0000000..a7ee056 --- /dev/null +++ b/docs/source/api/BarcodeSet.rst @@ -0,0 +1,11 @@ +BarcodeSet +========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::BarcodeSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Cigar.rst b/docs/source/api/Cigar.rst new file mode 100644 index 0000000..cea30d5 --- /dev/null +++ b/docs/source/api/Cigar.rst @@ -0,0 +1,11 @@ +Cigar +===== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::Cigar + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/CigarOperation.rst b/docs/source/api/CigarOperation.rst new file mode 100644 index 0000000..856400a --- /dev/null +++ b/docs/source/api/CigarOperation.rst @@ -0,0 +1,13 @@ +CigarOperation +============== + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::CigarOperationType + +.. doxygenclass:: PacBio::BAM::CigarOperation + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Compare.rst b/docs/source/api/Compare.rst new file mode 100644 index 0000000..bb28a7e --- /dev/null +++ b/docs/source/api/Compare.rst @@ -0,0 +1,8 @@ +Compare +======= + +.. code-block:: cpp + + #include + +.. doxygenfile:: Compare.h \ No newline at end of file diff --git a/docs/source/api/Config.rst b/docs/source/api/Config.rst new file mode 100644 index 0000000..c4be9e4 --- /dev/null +++ b/docs/source/api/Config.rst @@ -0,0 +1,8 @@ +Config +======= + +.. code-block:: cpp + + #include + +.. doxygenfile:: Config.h \ No newline at end of file diff --git a/docs/source/api/ConsensusAlignmentSet.rst b/docs/source/api/ConsensusAlignmentSet.rst new file mode 100644 index 0000000..bc5a7e5 --- /dev/null +++ b/docs/source/api/ConsensusAlignmentSet.rst @@ -0,0 +1,11 @@ +ConsensusAlignmentSet +===================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ConsensusAlignmentSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ConsensusReadSet.rst b/docs/source/api/ConsensusReadSet.rst new file mode 100644 index 0000000..846698d --- /dev/null +++ b/docs/source/api/ConsensusReadSet.rst @@ -0,0 +1,11 @@ +ConsensusReadSet +================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ConsensusReadSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ContigSet.rst b/docs/source/api/ContigSet.rst new file mode 100644 index 0000000..96bb20b --- /dev/null +++ b/docs/source/api/ContigSet.rst @@ -0,0 +1,11 @@ +ContigSet +========= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ContigSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/DataSet.rst b/docs/source/api/DataSet.rst new file mode 100644 index 0000000..8b3f0db --- /dev/null +++ b/docs/source/api/DataSet.rst @@ -0,0 +1,11 @@ +DataSet +======= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::DataSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/DataSetBase.rst b/docs/source/api/DataSetBase.rst new file mode 100644 index 0000000..f23fbb5 --- /dev/null +++ b/docs/source/api/DataSetBase.rst @@ -0,0 +1,11 @@ +DataSetBase +======= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::DataSetBase + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/DataSetMetadata.rst b/docs/source/api/DataSetMetadata.rst new file mode 100644 index 0000000..eea260d --- /dev/null +++ b/docs/source/api/DataSetMetadata.rst @@ -0,0 +1,11 @@ +DataSetMetadata +=============== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::DataSetMetadata + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/EntireFileQuery.rst b/docs/source/api/EntireFileQuery.rst new file mode 100644 index 0000000..4e7b86b --- /dev/null +++ b/docs/source/api/EntireFileQuery.rst @@ -0,0 +1,11 @@ +EntireFileQuery +=============== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::EntireFileQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ExtensionElement.rst b/docs/source/api/ExtensionElement.rst new file mode 100644 index 0000000..980303e --- /dev/null +++ b/docs/source/api/ExtensionElement.rst @@ -0,0 +1,11 @@ +ExtensionElement +================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ExtensionElement + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Extensions.rst b/docs/source/api/Extensions.rst new file mode 100644 index 0000000..6704807 --- /dev/null +++ b/docs/source/api/Extensions.rst @@ -0,0 +1,11 @@ +Extensions +================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::Extensions + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ExternalResource.rst b/docs/source/api/ExternalResource.rst new file mode 100644 index 0000000..03ab0d3 --- /dev/null +++ b/docs/source/api/ExternalResource.rst @@ -0,0 +1,11 @@ +ExternalResource +================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ExternalResource + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ExternalResources.rst b/docs/source/api/ExternalResources.rst new file mode 100644 index 0000000..bd72ea4 --- /dev/null +++ b/docs/source/api/ExternalResources.rst @@ -0,0 +1,11 @@ +ExternalResources +================= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ExternalResources + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/FileIndex.rst b/docs/source/api/FileIndex.rst new file mode 100644 index 0000000..c117214 --- /dev/null +++ b/docs/source/api/FileIndex.rst @@ -0,0 +1,11 @@ +FileIndex +========= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::FileIndex + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/FileIndices.rst b/docs/source/api/FileIndices.rst new file mode 100644 index 0000000..b25720c --- /dev/null +++ b/docs/source/api/FileIndices.rst @@ -0,0 +1,11 @@ +FileIndices +========= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::FileIndices + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Filter.rst b/docs/source/api/Filter.rst new file mode 100644 index 0000000..6faa8aa --- /dev/null +++ b/docs/source/api/Filter.rst @@ -0,0 +1,11 @@ +Filter +====== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::Filter + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Filters.rst b/docs/source/api/Filters.rst new file mode 100644 index 0000000..7ea1620 --- /dev/null +++ b/docs/source/api/Filters.rst @@ -0,0 +1,11 @@ +Filters +======= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::Filters + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Frames.rst b/docs/source/api/Frames.rst new file mode 100644 index 0000000..cf260f2 --- /dev/null +++ b/docs/source/api/Frames.rst @@ -0,0 +1,11 @@ +Frames +====== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::Frames + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/GenomicInterval.rst b/docs/source/api/GenomicInterval.rst new file mode 100644 index 0000000..811b83a --- /dev/null +++ b/docs/source/api/GenomicInterval.rst @@ -0,0 +1,11 @@ +GenomicInterval +=============== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::GenomicInterval + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/GenomicIntervalCompositeBamReader.rst b/docs/source/api/GenomicIntervalCompositeBamReader.rst new file mode 100644 index 0000000..f658621 --- /dev/null +++ b/docs/source/api/GenomicIntervalCompositeBamReader.rst @@ -0,0 +1,11 @@ +GenomicIntervalCompositeBamReader +================================= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::GenomicIntervalCompositeBamReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/GenomicIntervalQuery.rst b/docs/source/api/GenomicIntervalQuery.rst new file mode 100644 index 0000000..7bae558 --- /dev/null +++ b/docs/source/api/GenomicIntervalQuery.rst @@ -0,0 +1,11 @@ +GenomicIntervalQuery +==================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::GenomicIntervalQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/HdfSubreadSet.rst b/docs/source/api/HdfSubreadSet.rst new file mode 100644 index 0000000..88bf008 --- /dev/null +++ b/docs/source/api/HdfSubreadSet.rst @@ -0,0 +1,11 @@ +HdfSubreadSet +============= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::HdfSubreadSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/IndexResultBlock.rst b/docs/source/api/IndexResultBlock.rst new file mode 100644 index 0000000..fac804a --- /dev/null +++ b/docs/source/api/IndexResultBlock.rst @@ -0,0 +1,17 @@ +IndexResultBlock +================ + +.. code-block:: cpp + + #include + +.. doxygenstruct:: PacBio::BAM::IndexResultBlock + :members: + :protected-members: + :undoc-members: + +.. doxygentypedef:: PacBio::BAM::IndexResultBlocks + +.. doxygentypedef:: PacBio::BAM::IndexList + +.. doxygentypedef:: PacBio::BAM::IndexRange \ No newline at end of file diff --git a/docs/source/api/IndexedFastaReader.rst b/docs/source/api/IndexedFastaReader.rst new file mode 100644 index 0000000..7c46064 --- /dev/null +++ b/docs/source/api/IndexedFastaReader.rst @@ -0,0 +1,11 @@ +IndexedFastaReader +================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::IndexedFastaReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Interval.rst b/docs/source/api/Interval.rst new file mode 100644 index 0000000..f506a19 --- /dev/null +++ b/docs/source/api/Interval.rst @@ -0,0 +1,11 @@ +Interval +======== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::Interval + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/InvalidSequencingChemistryException.rst b/docs/source/api/InvalidSequencingChemistryException.rst new file mode 100644 index 0000000..d521ecc --- /dev/null +++ b/docs/source/api/InvalidSequencingChemistryException.rst @@ -0,0 +1,11 @@ +InvalidSequencingChemistryException +=================================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::InvalidSequencingChemistryException + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/LocalContextFlags.rst b/docs/source/api/LocalContextFlags.rst new file mode 100644 index 0000000..8cd63be --- /dev/null +++ b/docs/source/api/LocalContextFlags.rst @@ -0,0 +1,8 @@ +LocalContextFlags +================= + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::LocalContextFlags diff --git a/docs/source/api/NamespaceInfo.rst b/docs/source/api/NamespaceInfo.rst new file mode 100644 index 0000000..c7613ec --- /dev/null +++ b/docs/source/api/NamespaceInfo.rst @@ -0,0 +1,11 @@ +NamespaceInfo +============= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::NamespaceInfo + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/NamespaceRegistry.rst b/docs/source/api/NamespaceRegistry.rst new file mode 100644 index 0000000..2f8f9a7 --- /dev/null +++ b/docs/source/api/NamespaceRegistry.rst @@ -0,0 +1,11 @@ +NamespaceRegistry +================= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::NamespaceRegistry + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Orientation.rst b/docs/source/api/Orientation.rst new file mode 100644 index 0000000..e9bbc42 --- /dev/null +++ b/docs/source/api/Orientation.rst @@ -0,0 +1,8 @@ +Orientation +=========== + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::Orientation diff --git a/docs/source/api/ParentTool.rst b/docs/source/api/ParentTool.rst new file mode 100644 index 0000000..e2ffa1b --- /dev/null +++ b/docs/source/api/ParentTool.rst @@ -0,0 +1,11 @@ +ParentTool +========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ParentTool + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiBuilder.rst b/docs/source/api/PbiBuilder.rst new file mode 100644 index 0000000..d795d0f --- /dev/null +++ b/docs/source/api/PbiBuilder.rst @@ -0,0 +1,11 @@ +PbiBuilder +========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiBuilder + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiFile.rst b/docs/source/api/PbiFile.rst new file mode 100644 index 0000000..5a8b85a --- /dev/null +++ b/docs/source/api/PbiFile.rst @@ -0,0 +1,14 @@ +PbiFile +======= + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::PbiFile::Section + +.. doxygentypedef:: PacBio::BAM::PbiFile::Sections + +.. doxygenenum:: PacBio::BAM::PbiFile::VersionEnum + +.. doxygenfunction:: PacBio::BAM::PbiFile::CreateFrom diff --git a/docs/source/api/PbiFilter.rst b/docs/source/api/PbiFilter.rst new file mode 100644 index 0000000..261498b --- /dev/null +++ b/docs/source/api/PbiFilter.rst @@ -0,0 +1,11 @@ +PbiFilter +========= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiFilter + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiFilterCompositeBamReader.rst b/docs/source/api/PbiFilterCompositeBamReader.rst new file mode 100644 index 0000000..7a69df3 --- /dev/null +++ b/docs/source/api/PbiFilterCompositeBamReader.rst @@ -0,0 +1,11 @@ +PbiFilterCompositeBamReader +=========================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiFilterCompositeBamReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiFilterQuery.rst b/docs/source/api/PbiFilterQuery.rst new file mode 100644 index 0000000..75bbc12 --- /dev/null +++ b/docs/source/api/PbiFilterQuery.rst @@ -0,0 +1,11 @@ +PbiFilterQuery +============== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiFilterQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiFilterTypes.rst b/docs/source/api/PbiFilterTypes.rst new file mode 100644 index 0000000..052389b --- /dev/null +++ b/docs/source/api/PbiFilterTypes.rst @@ -0,0 +1,8 @@ +PbiFilterTypes +============== + +.. code-block:: cpp + + #include + +.. doxygenfile:: PbiFilterTypes.h \ No newline at end of file diff --git a/docs/source/api/PbiIndexedBamReader.rst b/docs/source/api/PbiIndexedBamReader.rst new file mode 100644 index 0000000..5450c8a --- /dev/null +++ b/docs/source/api/PbiIndexedBamReader.rst @@ -0,0 +1,11 @@ +PbiIndexedBamReader +=================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiIndexedBamReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiRawBarcodeData.rst b/docs/source/api/PbiRawBarcodeData.rst new file mode 100644 index 0000000..c72ebfb --- /dev/null +++ b/docs/source/api/PbiRawBarcodeData.rst @@ -0,0 +1,11 @@ +PbiRawBarcodeData +================= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiRawBarcodeData + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiRawBasicData.rst b/docs/source/api/PbiRawBasicData.rst new file mode 100644 index 0000000..2282387 --- /dev/null +++ b/docs/source/api/PbiRawBasicData.rst @@ -0,0 +1,11 @@ +PbiRawBasicData +=============== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiRawBasicData + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiRawData.rst b/docs/source/api/PbiRawData.rst new file mode 100644 index 0000000..1a974e8 --- /dev/null +++ b/docs/source/api/PbiRawData.rst @@ -0,0 +1,11 @@ +PbiRawData +========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiRawData + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiRawMappedData.rst b/docs/source/api/PbiRawMappedData.rst new file mode 100644 index 0000000..42e1de1 --- /dev/null +++ b/docs/source/api/PbiRawMappedData.rst @@ -0,0 +1,11 @@ +PbiRawMappedData +================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiRawMappedData + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiRawReferenceData.rst b/docs/source/api/PbiRawReferenceData.rst new file mode 100644 index 0000000..460cde4 --- /dev/null +++ b/docs/source/api/PbiRawReferenceData.rst @@ -0,0 +1,11 @@ +PbiRawReferenceData +=================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiRawReferenceData + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/PbiReferenceEntry.rst b/docs/source/api/PbiReferenceEntry.rst new file mode 100644 index 0000000..472e586 --- /dev/null +++ b/docs/source/api/PbiReferenceEntry.rst @@ -0,0 +1,11 @@ +PbiReferenceEntry +================= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::PbiReferenceEntry + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Position.rst b/docs/source/api/Position.rst new file mode 100644 index 0000000..3c945f2 --- /dev/null +++ b/docs/source/api/Position.rst @@ -0,0 +1,10 @@ +Position +======== + +.. code-block:: cpp + + #include + +.. doxygentypedef:: PacBio::BAM::Position + +.. doxygenvariable:: PacBio::BAM::UnmappedPosition \ No newline at end of file diff --git a/docs/source/api/ProgramInfo.rst b/docs/source/api/ProgramInfo.rst new file mode 100644 index 0000000..b58c93a --- /dev/null +++ b/docs/source/api/ProgramInfo.rst @@ -0,0 +1,11 @@ +ProgramInfo +=========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ProgramInfo + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/QNameQuery.rst b/docs/source/api/QNameQuery.rst new file mode 100644 index 0000000..b549436 --- /dev/null +++ b/docs/source/api/QNameQuery.rst @@ -0,0 +1,11 @@ +QNameQuery +========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::QNameQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/QualityValue.rst b/docs/source/api/QualityValue.rst new file mode 100644 index 0000000..3520c5a --- /dev/null +++ b/docs/source/api/QualityValue.rst @@ -0,0 +1,11 @@ +QualityValue +============ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::QualityValue + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/QualityValues.rst b/docs/source/api/QualityValues.rst new file mode 100644 index 0000000..8f6dfa5 --- /dev/null +++ b/docs/source/api/QualityValues.rst @@ -0,0 +1,11 @@ +QualityValues +============= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::QualityValues + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ReadAccuracyQuery.rst b/docs/source/api/ReadAccuracyQuery.rst new file mode 100644 index 0000000..abfd1e6 --- /dev/null +++ b/docs/source/api/ReadAccuracyQuery.rst @@ -0,0 +1,11 @@ +ReadAccuracyQuery +================= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ReadAccuracyQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ReadGroupInfo.rst b/docs/source/api/ReadGroupInfo.rst new file mode 100644 index 0000000..7fb4f69 --- /dev/null +++ b/docs/source/api/ReadGroupInfo.rst @@ -0,0 +1,21 @@ +ReadGroupInfo +============= + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::BaseFeature + +.. doxygenenum:: PacBio::BAM::FrameCodec + +.. doxygenenum:: PacBio::BAM::BarcodeModeType + +.. doxygenenum:: PacBio::BAM::BarcodeQualityType + +.. doxygenclass:: PacBio::BAM::ReadGroupInfo + :members: + :protected-members: + :undoc-members: + +.. doxygenfunction:: PacBio::BAM::MakeReadGroupId \ No newline at end of file diff --git a/docs/source/api/ReferenceSet.rst b/docs/source/api/ReferenceSet.rst new file mode 100644 index 0000000..22e4703 --- /dev/null +++ b/docs/source/api/ReferenceSet.rst @@ -0,0 +1,11 @@ +ReferenceSet +============ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ReferenceSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/SamTagCodec.rst b/docs/source/api/SamTagCodec.rst new file mode 100644 index 0000000..4f8d65d --- /dev/null +++ b/docs/source/api/SamTagCodec.rst @@ -0,0 +1,11 @@ +SamTagCodec +=========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::SamTagCodec + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/SequenceInfo.rst b/docs/source/api/SequenceInfo.rst new file mode 100644 index 0000000..393d5bb --- /dev/null +++ b/docs/source/api/SequenceInfo.rst @@ -0,0 +1,11 @@ +SequenceInfo +============ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::SequenceInfo + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/SequentialCompositeBamReader.rst b/docs/source/api/SequentialCompositeBamReader.rst new file mode 100644 index 0000000..31ed3b1 --- /dev/null +++ b/docs/source/api/SequentialCompositeBamReader.rst @@ -0,0 +1,11 @@ +SequentialCompositeBamReader +============================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::SequentialCompositeBamReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Strand.rst b/docs/source/api/Strand.rst new file mode 100644 index 0000000..4978f72 --- /dev/null +++ b/docs/source/api/Strand.rst @@ -0,0 +1,8 @@ +Strand +====== + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::Strand diff --git a/docs/source/api/SubDataSets.rst b/docs/source/api/SubDataSets.rst new file mode 100644 index 0000000..d179065 --- /dev/null +++ b/docs/source/api/SubDataSets.rst @@ -0,0 +1,11 @@ +SubDataSets +=========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::SubDataSets + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/SubreadLengthQuery.rst b/docs/source/api/SubreadLengthQuery.rst new file mode 100644 index 0000000..23000b3 --- /dev/null +++ b/docs/source/api/SubreadLengthQuery.rst @@ -0,0 +1,11 @@ +SubreadLengthQuery +================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::SubreadLengthQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/SubreadSet.rst b/docs/source/api/SubreadSet.rst new file mode 100644 index 0000000..bfc3c13 --- /dev/null +++ b/docs/source/api/SubreadSet.rst @@ -0,0 +1,11 @@ +SubreadSet +========== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::SubreadSet + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/Tag.rst b/docs/source/api/Tag.rst new file mode 100644 index 0000000..50b85c7 --- /dev/null +++ b/docs/source/api/Tag.rst @@ -0,0 +1,15 @@ +Tag +=== + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::TagDataType + +.. doxygenenum:: PacBio::BAM::TagModifier + +.. doxygenclass:: PacBio::BAM::Tag + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/TagCollection.rst b/docs/source/api/TagCollection.rst new file mode 100644 index 0000000..1314b13 --- /dev/null +++ b/docs/source/api/TagCollection.rst @@ -0,0 +1,11 @@ +TagCollection +============= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::TagCollection + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/VirtualPolymeraseBamRecord.rst b/docs/source/api/VirtualPolymeraseBamRecord.rst new file mode 100644 index 0000000..06d5531 --- /dev/null +++ b/docs/source/api/VirtualPolymeraseBamRecord.rst @@ -0,0 +1,11 @@ +VirtualPolymeraseBamRecord +========================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::VirtualPolymeraseBamRecord + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/VirtualPolymeraseCompositeReader.rst b/docs/source/api/VirtualPolymeraseCompositeReader.rst new file mode 100644 index 0000000..e6cab4e --- /dev/null +++ b/docs/source/api/VirtualPolymeraseCompositeReader.rst @@ -0,0 +1,11 @@ +VirtualPolymeraseCompositeReader +================================ + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::VirtualPolymeraseCompositeReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/VirtualPolymeraseReader.rst b/docs/source/api/VirtualPolymeraseReader.rst new file mode 100644 index 0000000..14a46e8 --- /dev/null +++ b/docs/source/api/VirtualPolymeraseReader.rst @@ -0,0 +1,11 @@ +VirtualPolymeraseReader +======================= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::VirtualPolymeraseReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/VirtualRegion.rst b/docs/source/api/VirtualRegion.rst new file mode 100644 index 0000000..7a09846 --- /dev/null +++ b/docs/source/api/VirtualRegion.rst @@ -0,0 +1,11 @@ +VirtualRegion +============= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::VirtualRegion + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/VirtualRegionType.rst b/docs/source/api/VirtualRegionType.rst new file mode 100644 index 0000000..4279200 --- /dev/null +++ b/docs/source/api/VirtualRegionType.rst @@ -0,0 +1,8 @@ +VirtualRegionType +================= + +.. code-block:: cpp + + #include + +.. doxygenenum:: PacBio::BAM::VirtualRegionType diff --git a/docs/source/api/VirtualRegionTypeMap.rst b/docs/source/api/VirtualRegionTypeMap.rst new file mode 100644 index 0000000..eebe637 --- /dev/null +++ b/docs/source/api/VirtualRegionTypeMap.rst @@ -0,0 +1,11 @@ +VirtualRegionTypeMap +==================== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::VirtualRegionTypeMap + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ZmwGroupQuery.rst b/docs/source/api/ZmwGroupQuery.rst new file mode 100644 index 0000000..01fc18a --- /dev/null +++ b/docs/source/api/ZmwGroupQuery.rst @@ -0,0 +1,11 @@ +ZmwGroupQuery +============= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ZmwGroupQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ZmwQuery.rst b/docs/source/api/ZmwQuery.rst new file mode 100644 index 0000000..375fcb0 --- /dev/null +++ b/docs/source/api/ZmwQuery.rst @@ -0,0 +1,11 @@ +ZmwQuery +======== + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ZmwQuery + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api/ZmwWhitelistVirtualReader.rst b/docs/source/api/ZmwWhitelistVirtualReader.rst new file mode 100644 index 0000000..95d2d1a --- /dev/null +++ b/docs/source/api/ZmwWhitelistVirtualReader.rst @@ -0,0 +1,11 @@ +ZmwWhitelistVirtualReader +========================= + +.. code-block:: cpp + + #include + +.. doxygenclass:: PacBio::BAM::ZmwWhitelistVirtualReader + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/docs/source/api_reference.rst b/docs/source/api_reference.rst new file mode 100644 index 0000000..354c0de --- /dev/null +++ b/docs/source/api_reference.rst @@ -0,0 +1,12 @@ +.. _api_reference: + +C++ API Reference +================= + +Watch this space for more recipes & how-tos. + +.. toctree:: + :maxdepth: 1 + :glob: + + api/* diff --git a/docs/source/commandline_utilities.rst b/docs/source/commandline_utilities.rst new file mode 100644 index 0000000..7f1bdaf --- /dev/null +++ b/docs/source/commandline_utilities.rst @@ -0,0 +1,15 @@ +.. _command_line: + +Command Line Utilities +====================== + +In addition to the main library and wrappers, pbbam also provides a few basic +utilities for working with PacBio indices (".pbi" files). + +.. toctree:: + :maxdepth: 1 + + tools/bam2sam + tools/pbindex + tools/pbindexdump + tools/pbmerge diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100755 index 0000000..8fb7646 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,332 @@ +# -*- coding: utf-8 -*- +# +# pbbam documentation build configuration file, created by +# sphinx-quickstart on Fri Dec 4 10:08:52 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex +import re +import subprocess + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# get RTD to run doxygen first, per http://breathe.readthedocs.org/en/latest/readthedocs.html +# but... we generate our actual Doxyfile via CMake in a normal build, +# so we need to create one here, subbing actual values +read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' +if read_the_docs_build: + + # fetch directory info + this_dir = os.path.abspath(os.getcwd()) + docs_dir = os.path.abspath(os.path.join(this_dir, '..')) + root_dir = os.path.abspath(os.path.join(docs_dir, '..')) + include_dir = os.path.abspath(os.path.join(root_dir, 'include')) + + # get project version + version = '' + with open(os.path.abspath(os.path.join(root_dir, 'CMakeLists.txt')), 'r') as cmakeFile: + for line in cmakeFile: + if line.startswith('project'): + version = re.search(r'VERSION\s*([\d.]+)', line).group(1) + break + + # read Doxyfile.in, replace markers with real values, and write Doxyfile + inDoxyfile = open(os.path.abspath(os.path.join(docs_dir, 'Doxyfile.in')), 'r') + configIn = inDoxyfile.read() + configOut = re.sub('@PacBioBAM_NAME@', 'pbbam', \ + re.sub('@PacBioBAM_VERSION@', version, \ + re.sub('@PacBioBAM_DocsDir@', docs_dir, \ + re.sub('@PacBioBAM_IncludeDir@', include_dir, configIn)))) + outDoxyfile = open(os.path.abspath(os.path.join(docs_dir, 'Doxyfile')), 'w') + #print(configOut, outDoxyfile) + print >>outDoxyfile, configOut + outDoxyfile.close() + + # now run Doxygen + subprocess.call('cd ..; doxygen', shell=True) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['breathe'] +#extensions = [ +# 'sphinx.ext.autodoc', + # 'sphinx.ext.coverage', + # 'breathe', +#] + +# Setup Breathe extension varialbes +breathe_projects = { 'pbbam' : os.path.join(os.getcwd(), '..', 'xml') + os.path.sep } +breathe_default_project = 'pbbam' +breathe_default_members = ('members', 'undoc-members') +breathe_implementation_filename_extensions = [ '.cpp', '.inl' ] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'pbbam' +copyright = u'2015, Derek Barnett' +author = u'Derek Barnett' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0.6' +# The full version, including alpha/beta/rc tags. +release = '1.0.6' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'pacbio-theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ['.'] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pbbamdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pbbam.tex', u'pbbam Documentation', + u'Derek Barnett', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pbbam', u'pbbam Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pbbam', u'pbbam Documentation', + author, 'pbbam', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst new file mode 100644 index 0000000..a69a987 --- /dev/null +++ b/docs/source/getting_started.rst @@ -0,0 +1,105 @@ + +.. _getting_started: + +Getting Started +=============== + +.. _getting_started-requirements: + +Requirements +------------ + +These components will almost certainly already be on your system. + +* `gcc`_ (4.8+) OR `clang`_ (v3.1+) +* pthreads +* zlib + +Double-check your compiler version, to be sure it is compatible. + +.. code-block:: console + + $ g++ -v + $ clang -v + +Additional requirements: + +* `Boost`_ (1.55+) +* `Meson`_ (0.48+) +* `Google Test`_ +* `htslib`_ (1.4+) + +For building API documentation locally: + +* `Doxygen`_ + +For maximal convenience, install htslib and google test in the same parent directory you plan to install pbbam. + +.. _Boost: http://www.boost.org/ +.. _clang: http://clang.llvm.org/ +.. _Meson: https://mesonbuild.com +.. _Ninja: https://ninja-build.org/ (only required when using Meson, optional for CMake) +.. _Doxygen: http://www.stack.nl/~dimitri/doxygen/ +.. _gcc: https://gcc.gnu.org/ +.. _Google Test: https://github.com/google/googletest +.. _htslib: https://github.com/samtools/htslib.git + +.. _getting_started-build: + +Clone & Build +------------- + +.. note:: + + The following steps are for building the C++ library and command-line utilities. + If you are integrating pbbam into a C#, Python, or R project, take a look at the + instructions for :ref:`additional languages `. + +The basic steps for obtaining pbbam and building it from source are as follows: + +Build and install htslib, per the project's instructions (or on OSX "brew install htslib"). + +Clone +^^^^^ + +You should first clone the repository: + +.. code-block:: console + + $ git clone https://github.com/PacificBiosciences/pbbam.git + $ cd pbbam + +Building with Meson +^^^^^^^^^^^^^^^^^^^ + +Building with Meson is generally faster and more versatile. Meson strictly requires building out of source: + +.. code-block:: console + + $ mkdir build + $ cd build + $ meson --prefix /my/install/prefix -Dtests=true .. + $ ninja + +where ninja will by default utilize a number of threads for compilation equal to the number of logical +cores on your system. Here ``-Dtests=true`` enables pulling in dependencies for testing. In +order to run the test suite, run: + +.. code-block:: console + + $ ninja test + +If you wish to install pbbam, run: + +.. code-block:: console + + $ ninja install + +and ninja will install pbbam to ``/my/install/prefix``. + +Integrate +--------- + +If you built and installed pbbam, pkg-config files will be available to be consumed by projects +wishing to utilize pbbam. Autoconf, CMake, Waf, SCons and Meson all have means to determine +dependency information from pkg-config files. diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..426c3c5 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,33 @@ +.. pbbam documentation master file, created by + sphinx-quickstart on Fri Dec 4 10:08:52 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. _home: + +pbbam documentation +=================== + +As of the 3.0 release of SMRTanalysis, PacBio is embracing the industry standard BAM +format for (both aligned and unaligned) basecall data files. We have also formulated +a BAM companion file format (bam.pbi) enabling fast access to a richer set of per-read +information as well as compatibility for software built around the legacy cmp.h5 format. + +The **pbbam** software package provides components to create, query, & edit PacBio BAM +files and associated indices. These components include a core C++ library, bindings for +additional languages, and command-line utilities. + +.. toctree:: + :maxdepth: 1 + + getting_started + api_reference + swig_bindings + commandline_utilities + + +Search: + +* :ref:`genindex` +* :ref:`search` + diff --git a/docs/source/pacbio-theme/static/headerGradient.jpg b/docs/source/pacbio-theme/static/headerGradient.jpg new file mode 100644 index 0000000000000000000000000000000000000000..883f147e6c9560851c7b8bb1b38e9382e1348954 GIT binary patch literal 7099 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 FzW{1@AD93D literal 0 HcmV?d00001 diff --git a/docs/source/pacbio-theme/static/pacbio.css b/docs/source/pacbio-theme/static/pacbio.css new file mode 100644 index 0000000..b4ab87f --- /dev/null +++ b/docs/source/pacbio-theme/static/pacbio.css @@ -0,0 +1,238 @@ +/** + * Sphinx stylesheet -- default theme + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Arial, sans-serif; + font-size: 100%; + background-color: #555; + color: #555; + margin: 0; + padding: 0; + min-width: 500px; + max-width: 956px; + margin: 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 230px; +} + +hr{ + border: 1px solid #B1B4B6; + +} + +div.document { + background-color: #eee; +} + +div.body { + background-color: #ffffff; + color: #3E4349; + padding: 30px 30px 30px 30px; + font-size: 0.8em; +} + +div.footer { + color: #555; + background-color: #fff; + padding: 13px 0; + text-align: center; + font-size: 75%; + +} +div.footer a { + color: #444; + text-decoration: underline; +} + +div.related { + background: #fff url(headerGradient.jpg); + line-height: 80px; + color: #fff; + font-size: 0.80em; + height: 79px; + z-index: -1; +} + +div.related ul { + background: url(pacbioLogo.png) 10px no-repeat; + padding: 0 0 0 200px; +} + +div.related a { + color: #E2F3CC; +} + +div.sphinxsidebar { + font-size: 0.75em; + line-height: 1.5em; +} + +div.sphinxsidebarwrapper{ + padding: 20px 0; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Arial, sans-serif; + color: #222; + font-size: 1.2em; + font-weight: bold; + margin: 0; + padding: 5px 10px 0 10px; +} + +div.sphinxsidebar h4{ + font-size: 1.1em; +} + +div.sphinxsidebar h3 a { + color: #444; +} + + +div.sphinxsidebar p { + color: #888; + padding: 0px 20px; + margin-top: 5px; +} + +div.sphinxsidebar p.topless { +} + +div.sphinxsidebar ul { + margin: 5px 20px 10px 20px; + padding: 0; + color: #000; +} + +div.sphinxsidebar a { + color: #444; +} + +div.sphinxsidebar input { + border: 1px solid #ccc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar input[type=text]{ + margin-left: 20px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #005B81; + text-decoration: none; +} + +a:hover { + color: #E32E00; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Arial, sans-serif; + font-weight: bold; + color: #264868; + margin: 30px 0px 10px 0px; + padding: 5px 0 5px 0px; +} + +div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 180%; font-weight: normal; } +div.body h2 { font-size: 125%; } +div.body h3 { font-size: 110%; } +div.body h4 { font-size: 100%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #c60f0f; + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + background-color: #c60f0f; + color: white; +} + +div.body p, div.body dd, div.body li { + line-height: 1.5em; + font-size: 1em; +} + +div.admonition p.admonition-title + p { + display: inline; +} + +div.highlight{ + background-color: white; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre { + padding: 10px; + background-color: White; + color: #222; + line-height: 1.2em; + border: 1px solid #C6C9CB; + font-size: 1.2em; + margin: 1.5em 0 1.5em 0; + -webkit-box-shadow: 1px 1px 1px #d8d8d8; + -moz-box-shadow: 1px 1px 1px #d8d8d8; +} + +tt { + background-color: #ecf0f3; + color: #222; + padding: 1px 2px; + font-size: 1.2em; + font-family: monospace; +} + diff --git a/docs/source/pacbio-theme/static/pacbioLogo.png b/docs/source/pacbio-theme/static/pacbioLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..b2e4887b12d19e498b2390551bec828d18f27915 GIT binary patch literal 3128 zcmV-849D|{P)DDTkIz_xVB(6~y5HClp(S9$KWt2h;;avBma)_TWS+9H5mQ!38c!KwAke zekqr7pzGZONaT>WQW5mfuD3-3sYqeIx4+N%GMSn8{QR7>&HJR0?dSPFzxmDgeKYfB z)tGYqz9-B2qo%_Z9V$AM%{Y%fTN{4ml@|wlFTb|CclFinXa4)kDzK0GVQ`#-m znbPm-Z~*|S>;EZDmGcyJ=!uml^i3d9_m(J^2%(R1sf-;oo^mrLw=mKgP% zE_cIME+&a=&)EYibkfQR*MT~`3nrhI5C|eLXB{A;K@YLau86o5p+owZn!sKK;Pa4* zm;i}tj%k3M8KAQ2+SVb@k!hf7_C->dCU1)wt4wf8h9w0M{l4(oyzl*)+h=gJHBHmh!y7 zvg>#rIaZcJd_aXWzswH_m;|sdeD@h=LIU1jf4HvR(cojb^wRg@bf!>#6dri$arM}> zRkio>YijT6tF~;3RhKfhrRrEFL*bI5HV)wPG=W1#RT!%ee3%_iN6ywn;w8XT~)#*wVhy5Zvz0!VBH>6 zfPG?5cn~P?j#R7{=eausAE_*N^(4yuxBxYi-;|c_FJD_7u_+1ZooR&`JN7IbPd84T zBIS3y2l#&@1*2^+xb^P_47&k5B7KB9K)qn>9)*a@hEbTM?kKm4JUS`LJu^VHvKQ%+ zE}{RP_~XxGkV$rYcnqMDy#4Ffk1;c(JO&H(e0%C-n7~0ErpT*>xI>Ya4uDAc9D&JX zXQXT5doyXD-&c34Yua+pn$>?yp7_JhM(!tOKGG@4aAF1|kV-xEv&R9KRm!T6Lec=0 zgnXWlU9)di*?ge{=0XZNaiFqmiTt2)cgge!u>aKOC9ui)M<2eY;|@P4Mxv0(fZG4k zw-PgX0Q#(JTh%7!rh>)DI5oiz6@_6M!v&rNHUI}{EOMD9jsAQ}{SfeYnVOGNr3oAe%nCk=!Y`u zav<8Y&+alKZa+nRS|WbU)Aq6`zk{%aKHi#DW9%`z0LRupGb1_meUAUjzj$e6kdeV= zku2_)$N+drw2L}u!Nm#yA)mt?!VN@QnsW+QK#<4iKr=vfL)3Q%-lgfE=C30<+YW{pLVZq@lW8^t5x3#`R@*P^hlW z6w5J#v}b}*fS6VU^O9jR#S+f_Wlr9MFqH>)Ta;BD63j)sIe{Z2)k~D&b(cMdvTsbW-$h z8xxdvN!LZ3QQTQNsdW9mCkL*uSkvcr^-LS;3O5F?tHAn!A(uj(kw^(AafQbS_D)04so!dwUdxP1B}bq#2ETa}f##)IdZSjJ?zcXMD#))ifo$)>+H zVEB;=usMaZ0v%u13DxE{RG^B)8s1f~;X4REYv@(|Q*_&{Pk6_l25Hx_>=StDB@`EU zFFr>dnAm3VzGr3#Rf@FZ|r*p5jyQUR3bT?8400Cqb?f3;w2R*e3tfN8JT z^y4Ey)gTEqtFEilx!^aLkWEQ;ZHJ+2qg_4JBXGU-1WQ$2 z=+Th?o{Nd+ER&_=0ykKgHypw#P1;DTT;}z3RwvdxlW8rb;ptLI7PGEs$AAiEtDXR} z<_*$0aT=aOUFhAR&7i_F)?K^UMlJJFhh>uUSQktEHh|a1wrGhbhH&mnKP&5Ab-7)N zGV1E^bv{XkU&+!=8A?eifU>-41%}K3&-aZs@m6s~*)J7VJoTxduOh_j%Xe<^7O7AT zLZ?OMVWZaT=fAc#1(1eV?xP$Sv!#+>UP0w8!M_;*c%js@0G5t&->*Ni110pez%vn> z(vnS4#yT5(WJ*>Or@<_}i zwHoh*>Zp8Pnie~tPxJk#7^FI8Z_hG-{9aN96L}JP9s?u5l2#FI%5T})DDtlfgRqy-rU=Gr&tm+Qla_tUWHsOWx|{Tlf|;~{z$<^&G6HtwS1jH* zT}USVdfWtQ-r=tfPx!=4QM|*ykcoln*{Um~kdKU + + pbindex creates a index file that enables random-access to PacBio-specific data + in BAM files. Generated index filename will be the same as input BAM plus .pbi suffix. + + Options: + -h, --help show this help message and exit + --version show program's version number and exit + + Input/Output: + input Input BAM file diff --git a/docs/source/tools/pbindexdump.rst b/docs/source/tools/pbindexdump.rst new file mode 100644 index 0000000..6829064 --- /dev/null +++ b/docs/source/tools/pbindexdump.rst @@ -0,0 +1,233 @@ +.. _pbindexdump: + +pbindexdump +=========== + +:: + + Usage: pbindexdump [options] [input] + + pbindexdump prints a human-readable view of PBI data to stdout. + + Options: + -h, --help show this help message and exit + --version show program's version number and exit + + Input/Output: + input Input PBI file. If not provided, stdin will be used as input. + --format=STRING Output format, one of: + json, cpp + + json: pretty-printed JSON [default] + + cpp: copy/paste-able C++ code that can be used to + construct the equivalent PacBio::BAM::PbiRawData object + + JSON Formatting: + --json-indent-level=INT + JSON indent level [4] + --json-raw Prints fields in a manner that more closely reflects the + PBI file format - presenting data as per-field columns, + not per-record objects. + +JSON Output Schemas +------------------- + +Normal JSON: + +.. code-block:: JSON + + { + "type": "object", + "properties": { + "fileSections": { + "type": "array", + "items": { "type": "string" }, + }, + "numReads": { "type": "integer" }, + "reads": { + "type": "array", + "items": { + "type": "object", + "properties": { + "aEnd": { "type": "integer" }, + "aStart": { "type": "integer" }, + "bcForward": { "type": "integer" }, + "bcQuality": { "type": "integer" }, + "bcReverse": { "type": "integer" }, + "contextFlag": { "type": "integer" }, + "fileOffset": { "type": "integer" }, + "holeNumber": { "type": "integer" }, + "mapQuality": { "type": "integer" }, + "nM": { "type": "integer" }, + "nMM": { "type": "integer" }, + "qEnd": { "type": "integer" }, + "qStart": { "type": "integer" }, + "readQuality": { "type": "number" }, + "reverseStrand": { "type": "integer" }, + "rgId": { "type": "integer" }, + "tEnd": { "type": "integer" }, + "tId": { "type": "integer" }, + "tStart: { "type": "integer" } + }, + "required": [ + "contextFlag", + "fileOffset", + "holeNumber", + "qEnd", + "qStart", + "readQuality", + "rgId" + ] + } + }, + "references": { + "type": "array", + "items": { + "type": "object", + "properties": { + "beginRow": { "type": "integer" }, + "endRow": { "type": "integer" }, + "tId": { "type": "integer" } + }, + "required" : [ "beginRow", "endRow","tId" ] + } + }q + "version": { "type": "string" } + }, + "required": [ + "fileSections", + "numReads", + "reads", + "version" + ] + } + +"Raw" JSON: + +.. code-block:: JSON + + { + "type": "object", + "properties": { + "barcodeData" : { + "type" : "object", + "properties: { + "bcForward" : { + "type": "array", + "items" : { "type": "integer" } + }, + "bcQuality" : { + "type": "array", + "items" : { "type": "integer" } + }, + "bcReverse" : { + "type": "array", + "items" : { "type": "integer" } + } + } + }, + "basicData" : { + "type" : "object", + "properties: { + "contextFlag" : { + "type": "array", + "items" : { "type": "integer" } + }, + "fileOffset" : { + "type": "array", + "items" : { "type": "integer" } + }, + "holeNumber" : { + "type": "array", + "items" : { "type": "integer" } + }, + "qEnd" : { + "type": "array", + "items" : { "type": "integer" } + }, + "qStart" : { + "type": "array", + "items" : { "type": "integer" } + }, + "readQuality" : { + "type": "array", + "items" : { "type": "number" } + }, + "rgId : { + "type": "array", + "items" : { "type": "integer" } + } + } + }, + "fileSections": { + "type": "array", + "items": { "type": "string" }, + }, + "mappedData" : { + "type" : "object", + "properties: { + "aEnd" : { + "type": "array", + "items" : { "type": "integer" } + }, + "aStart" : { + "type": "array", + "items" : { "type": "integer" } + }, + "mapQuality" : { + "type": "array", + "items" : { "type": "integer" } + }, + "nM" : { + "type": "array", + "items" : { "type": "integer" } + }, + "nMM" : { + "type": "array", + "items" : { "type": "integer" } + }, + "readQuality" : { + "type": "array", + "items" : { "type": "number" } + }, + "reverseStrand" : { + "type": "array", + "items" : { "type": "integer" } + }, + "tEnd" : { + "type": "array", + "items" : { "type": "integer" } + }, + "tId" : { + "type": "array", + "items" : { "type": "integer" } + }, + "tStart" : { + "type": "array", + "items" : { "type": "integer" } + } + } + }, + "numReads": { "type": "integer" }, + "references": { + "type": "array", + "items": { + "type": "object", + "properties": { + "beginRow": { "type": "integer" }, + "endRow": { "type": "integer" }, + "tId": { "type": "integer" } + }, + "required" : [ "beginRow", "endRow","tId" ] + } + }, + "version" : { "type": "string" } + }, + "required": [ + "fileSections", + "numReads", + "basicData", + "version" + ] + } diff --git a/docs/source/tools/pbmerge.rst b/docs/source/tools/pbmerge.rst new file mode 100644 index 0000000..937ec56 --- /dev/null +++ b/docs/source/tools/pbmerge.rst @@ -0,0 +1,30 @@ +.. _pbmerge: + +pbmerge +======= + +:: + + Usage: pbmerge [options] [-o ] + + pbmerge merges PacBio BAM files. If the input is DataSetXML, any filters will be + applied. If no output filename is specified, new BAM will be written to stdout. + + Options: + -h, --help show this help message and exit + --version show program's version number and exit + + Input/Output: + -o output Output BAM filename. + --no-pbi Set this option to skip PBI index file creation. PBI + creation is automatically skipped if no output filename + is provided. + INPUT Input may be one of: + DataSetXML, list of BAM files, or FOFN + + fofn: pbmerge -o merged.bam bams.fofn + + bams: pbmerge -o merged.bam 1.bam 2.bam 3.bam + + xml: pbmerge -o merged.bam foo.subreadset.xml + diff --git a/docs/specs/pbbam.rst b/docs/specs/pbbam.rst new file mode 100644 index 0000000..993cae2 --- /dev/null +++ b/docs/specs/pbbam.rst @@ -0,0 +1,630 @@ +================================================================= +**pbbam Software Design & Functional Specification** +================================================================= +| *Version 0.1* +| *Pacific Biosciences Engineering Group* +| *Jan 29, 2016* + +1. Revision History +=================== + ++-------------+---------------+--------------------+---------------------------+ +| **Date** | **Revision** | **Author(s)** | **Comments** | ++=============+===============+====================+===========================+ +| 01-29-2016 | 0.1 | Derek Barnett | Initial draft created | +| | | | | ++-------------+---------------+--------------------+---------------------------+ + +2. Introduction +=============== + +2.1. Document Specification Identifier +-------------------------------------- + ++-----------------------------------+------------------------------------------+ +| **Document Specification Prefix** | **Description** | ++===================================+==========================================+ +| FS\_SA\_PBBAM\_ | Functional spec for pbbam | ++-----------------------------------+------------------------------------------+ + +2.2. Purpose +------------ + +This document is intended to describe the requirements and interface of the pbbam +library, which provides functionality for creating, querying, and editing PacBio +BAM files and associated file formats. + +2.3. Scope of Document +---------------------- + +This document covers the expected usage of the pbbam library, as well as any +desired or required performance characteristics with respect to quality or speed. + +This document does not provide installation instructions or API documentation. + +2.4. Glossary of Terms +---------------------- + +The table below specifies only terms specific to this document, and skips +acronyms/terms that are specified in `Pacific Biosciences Software Glossary`_. + +.. _Pacific Biosciences Software Glossary: http://smrtanalysis-docs/pb_sw_glossary.html + ++------------------+-----------------------------------------------------------+ +| **Acronym/Term** | **Description** | ++==================+===========================================================+ +| API | Application Programming Interface - a set of routines, | +| | protocols, and tools for building software applications. | +| | In this document , this will consist of one or more | +| | cooperating libraries that specify data structures, | +| | methods, etc. for use within a target programming | +| | language. | ++------------------+-----------------------------------------------------------+ +| Client | An application that uses the library. | ++------------------+-----------------------------------------------------------+ +| I/O | Input/output of data. | ++------------------+-----------------------------------------------------------+ + +2.5. References +--------------- + ++-------------+------------------------------+--------------------------------------+ +| **Ref No.** | **Document Name, Link** | **Description** | ++=============+==============================+======================================+ +| (1) | `BAM format`_ | General SAM/BAM specification | ++-------------+------------------------------+--------------------------------------+ +| (2) | `PacBio BAM`_ | PacBio BAM specification | ++-------------+------------------------------+--------------------------------------+ +| (3) | `PacBio BAM index`_ | PacBio BAM index specification | ++-------------+------------------------------+--------------------------------------+ +| (4) | `DataSet XML`_ | PacBio DataSet XML specification | ++-------------+------------------------------+--------------------------------------+ +| (5) | `Software Style Guide`_ | PacBio coding standards | ++-------------+------------------------------+--------------------------------------+ +| (6) | `SMRT Analysis`_ | General SMRT Analysis infrastructure | ++-------------+------------------------------+--------------------------------------+ + +.. _BAM format: https://samtools.github.io/hts-specs/SAMv1.pdf +.. _PacBio BAM: http://pacbiofileformats.readthedocs.org/en/3.0/BAM.html +.. _PacBio BAM index: http://pacbiofileformats.readthedocs.org/en/3.0/PacBioBamIndex.html +.. _DataSet XML: https://github.com/PacificBiosciences/PacBioFileFormats/blob/3.0/DataSet.rst +.. _Software Style Guide: http://smrtanalysis-docs/_downloads/PBISoftwareStyleGuide.doc +.. _SMRT Analysis: http://smrtanalysis-docs/smrt_docs.html + +3. Software Overview +==================== + +3.1. Product Description +------------------------ + +As of the 3.0 release of SMRTanalysis, PacBio is embracing the industry standard +`BAM format`_ (1) for (both aligned and unaligned) basecall data files. We have +also formulated a BAM companion file format (.bam.pbi) enabling fast access to a +richer set of per-read information as well as compatibility for software built +around the legacy cmp.h5 format. + +The pbbam library provides components to create, query, & transform PacBio BAM +data: sequence files and their associated indices. This includes a core C++ +library as well as bindings for additional programming languages. + +3.2. Product Functional Capabilities +------------------------------------ + +The library must be able to read and write BAM files that conform to the +`PacBio BAM`_ specification (2). BAM records must be editable e.g. adding +alignment information. Random access must be supported, whether by genomic +region or by filtering record features. To this end, the library will be able to +read, write, and create associated index files - both the standard BAM index +(.bai) and the `PacBio BAM index`_ (.pbi) (3). In addition to working with +individual files, datasets of related BAM files will be supported. These are +described in a `DataSet XML`_ document. (4) + +3.3. User Characteristics +------------------------- + ++---------------------+--------------------------------------------------------+ +| **User Class/Role** | **User Knowledge and Skill Levels** | ++=====================+========================================================+ +| Developer | Competence in one or more programming languages | +| | supported (C++, R, Python, C#). No knowledge of | +| | molecular biology wet lab techniques required. | ++---------------------+--------------------------------------------------------+ + +3.4. User Operations and Practices +---------------------------------- + +Developer users will interact with the software by incorporating the library +into a client application. + +3.5. Operating Environment +-------------------------- + +The software is intended to be run in a Linux or OSX environment, with ideally 4 +or more cores. + +3.6. Design and Implementation Constraints +------------------------------------------ + +Currently there are no constraints outside the operating environment and speed +requirements. In particular, as the library will be used for writing the BAM +files coming off a Sequel instrument, it should be able to keep pace. + +3.7. Assumptions and Dependencies +--------------------------------- + +Input routines for the library will expect to receive files that conform to the +`PacBio BAM`_ (2) or `DataSet XML`_ (4) specifications. + +The pbbam library depends on Boost, zlib, and htslib libraries. + +3.8. Other Software +------------------- + +Output PacBio BAMs will be compatible with the `PacBio BAM`_ specification (2) +and thus compatible with the general `BAM format`_ specification (1). This +ensures that a wide variety of downstream tools can interact with data files. + +The software uses `Meson`_ as its build system. + +The core C++ API relies on the following 3rd party components: + +* `zlib`_ +* `htslib`_ +* `Boost`_ (header-only modules) + +Wrapper APIs for additional languages (Python, R, C#) are generated by `SWIG`_. + +API documentation is generated via `Doxygen`_. + +.. _Meson: https://mesonbuild.com +.. _zlib: http://www.zlib.net/ +.. _htslib: https://github.com/samtools/htslib +.. _Boost: http://www.boost.org/ +.. _SWIG: http://www.swig.org/ +.. _Doxygen: http://www.stack.nl/~dimitri/doxygen/ + +4. External Interfaces +====================== + +4.1. User Interfaces +-------------------- + +N/A + +4.2. Software Interfaces +------------------------ + +pbbam will require the following software: + +* `htslib`_ & `zlib`_ - provides low-level handling of compressed BAM data +* `Boost`_ - provides utility classes + +Incoming data from upstream components will be compliant with +PacBio BAM format - see `PacBio BAM`_ specification (2) for more detail. + +4.3. Hardware Interfaces +------------------------ + +N/A + +4.4. Communications Interfaces +------------------------------ + +N/A + +5. Functional Requirements +========================== + +5.1. Query BAM data by genomic region +----------------------------------------- + +5.1.1. Description +~~~~~~~~~~~~~~~~~~ + +pbbam shall allow client applications to query data, limited to some genomic +region of interest. + +5.1.2. Inputs +~~~~~~~~~~~~~ + +* BAM file(s) or DataSet XML +* a standard index (.bai) for each source BAM file +* genomic interval (e.g. "chr1:1000-2000") + +5.1.3. Processing +~~~~~~~~~~~~~~~~~ + +Obtain an `htslib`_ "iterator" object for a given file and region. This will be +wrapped by pbbam to hide the low-level nature of this type, as well as handling +memory lifetime. + +5.1.4. Outputs +~~~~~~~~~~~~~~ + +Iterator providing access to individual BAM records from the input data sources, +which are aligned to the requested genomic interval. + +For example: + +.. code:: c++ + + GenomicIntervalQuery query(interval, dataset); + for (const BamRecord& record : query) { + // ... do stuff ... + } + + +5.1.5. Regulatory Compliance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +N/A + +5.2. Query BAM data by filter criteria +----------------------------------------- + +5.2.1. Description +~~~~~~~~~~~~~~~~~~ + +pbbam shall allow client applications to query data, limited to some filter +criteria (e.g. only reads from ZMW hole number 200 with a read quality of >0.5). + +5.2.2. Inputs +~~~~~~~~~~~~~ + +* BAM file(s) or DataSet XML +* a `PacBio BAM index`_ (.pbi) for each source BAM file +* filters supported by data contained in the PBI + +5.2.3. Processing +~~~~~~~~~~~~~~~~~ + +Query PBI files(s) for records that match the provided filter criteria. Merge +contiguous runs of records into record blocks, to minimize seeks. Advancing the +iterator either reads the next read from the current block or seeks to the next +block and fetches the next record. + +5.2.4. Outputs +~~~~~~~~~~~~~~ + +Iterator providing access to individual BAM records from the input data sources, +which satisfy the requested filter criteria. + +For example: + +.. code:: c++ + + PbiFilterQuery query(filter, dataset); + for (const BamRecord& record : query) { + // ... do stuff ... + } + +5.2.5. Regulatory Compliance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +N/A + +5.3. Write PacBio BAM data +------------------------------------------ + +5.3.1. Description +~~~~~~~~~~~~~~~~~~ + +pbbam shall be able to write `PacBio BAM`_ files conforming to the specification. + +5.3.2. Inputs +~~~~~~~~~~~~~ + +* filename +* header information +* BAM records + +5.3.3. Processing +~~~~~~~~~~~~~~~~~ + +Create file handle for the provided filename, output initial header information. +As records are passed in, write to file. Upon completion, flush any buffers and +close file handle. + +Multithreading, provided by `htslib`_, will be utilized where possible to speed +up the compression process - often then main bottleneck of BAM throughput. + +5.3.4. Outputs +~~~~~~~~~~~~~~ + +BAM file conforming to the `PacBio BAM`_ specification. + +5.3.5. Regulatory Compliance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +N/A + +5.4. Create PacBio BAM index file +------------------------------------------ + +5.4.1. Description +~~~~~~~~~~~~~~~~~~ + +Much of PacBio BAM data processing relies on the presence of a `PacBio BAM index`_ +file. pbbam shall be able to generate this file type for a `PacBio BAM`_ file. + +5.4.2. Inputs +~~~~~~~~~~~~~ + +`PacBio BAM`_ file + +5.4.3. Processing +~~~~~~~~~~~~~~~~~ + +Read through the input BAM records, storing the values relevant to a PBI index. +At end of file, write the index contents to a file and close. + +5.4.4. Outputs +~~~~~~~~~~~~~~ + +`PacBio BAM index`_ file + +5.4.5. Regulatory Compliance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +N/A + +6. Non-Functional Requirements +============================== + +6.1. Performance Requirements +----------------------------- + +Since pbbam will be used to write all BAM files coming off a Sequel device, the +library must keep pace with data generation requirements. + +** come back to this, hard numbers ?? ** + +6.2. Safety Requirements +------------------------ + +N/A + +6.3. Security Requirements +-------------------------- + +N/A + +6.4. Quality Attributes +----------------------- + +6.4.1. Availability +~~~~~~~~~~~~~~~~~~~ + +N/A + +6.4.2. Integrity +~~~~~~~~~~~~~~~~ + +Inputs and outputs shall adhere to the PacBio BAM or DataSet XML specifications. +Files that do not meet this requirement will raise exceptions and will not be +accepted. + +6.4.3. Interoperability +~~~~~~~~~~~~~~~~~~~~~~~ + +Inputs and outputs shall adhere to the PacBio BAM or DataSet XML specifications. + +6.4.4. Reliability +~~~~~~~~~~~~~~~~~~ + +The developed software shall meet the overall product reliability requirements. + +6.4.5. Robustness +~~~~~~~~~~~~~~~~~ + +pbbam will raise exceptions upon encountering failure cases, allowing client +applications to recover or report the error to a UI. + +6.4.6. Usability +~~~~~~~~~~~~~~~~ + +pbbam shall have comprehensive API documentation, available both on- and offline. +Further documentation will be provided for installation, API usage tips, etc. + +Raised exceptions shall carry as much information as possible so that client +applications can respond with appropriate actions or display useful messages. + +6.4.7. Maintainability +~~~~~~~~~~~~~~~~~~~~~~ + +The source code of the software covered in this functional specification shall +adhere to the PacBio `Software Style Guide`_ (9) work instruction, to guarantee +high quality of code that facilitates maintainability. + +6.4.8. Customizability +~~~~~~~~~~~~~~~~~~~~~~ + +N/A + +6.5. Business Rules +------------------- + +N/A + +6.6. Installation and Upgrade +----------------------------- + +Installation and Upgrade of this software will be handled as part of the SMRT +Analysis subsystem. See `SMRT Analysis`_ (6) specifications for more detail. + +Additionally, the library may be built independently, either from internal +version control (Perforce) or from the public-facing Github repository. In +either case, `Meson`_ is used to drive the build process. + +6.7. Administration +------------------- + +N/A + +6.8. User Documentation +----------------------- + +pbbam shall have comprehensive API documentation, available both on- and offline. +Further documentation will be provided for installation, API usage tips, etc. + +The "offline" API documentation may be built directly from the source code, using +`Doxygen`_. Online documentation will be generated via a continuous integration +server, thus ensuring it is always pointing to the current codebase. + +7. High Level Design +==================== + +7.1. Top Level Context +---------------------- + +The pbbam library is intended to be linked in with client applications, +providing programmatic access to data files. + +7.2. Use Cases +-------------- + +Primary use cases for pbbam include: + +* BAM file creation +* BAM file query - iterable access to various subsets of data + +8. Detailed Design +================== + +8.1. Structural Representation +------------------------------ + + *image(s) here* + +8.2. Behavioral Representation +------------------------------ + +This section provides behavioral (dynamic) representation of how the +elements of the system realize the required use cases. + +Describe how the significant subsystems and classes interact with each +other to realize the architecturally significant use cases. + +Provide a link to a file containing Sequence Diagram or Activity Diagram, when applicable. +The link may be provided with use of 'image' directive. + +Sequence Diagram shows one use case scenario, executed by class model, +with sequence of operations over period of time (time increased from top +to bottom). It shows interactions between objects, but does not show +relationships between them. + +Activity Diagram is a virtual representation of the sequential flow and +control logic of a set of related activities or actions. It is a type of +flowchart, frequently called Swim Lane Diagram, because activities of +each entity are presented within its swim lane. + +Note: You may use http://wsd tool to auto-generate a sequence diagram from +a descriptive text file, save the diagram to the wsd site, get link to the image, +and add this link to the document with use of 'image' directive. + +8.3. Information Storage +------------------------ + +pbbam software requires no persistent storage outside of availability of input +and output during analysis. + +8.4. Technology Overview +------------------------ + +pbbam is implemented in C++-11 and should perform as designed on any UNIX-like +operating system (Linux distributions, Apple OSX, etc.). + +8.5. SOUP Components +-------------------- + +pbbam utilizes Meson for its build system. The C++ library uses the following +3rd-party software components: Boost, htslib and zlib. + +8.6. Deployment and Configuration +--------------------------------- + +Please refer to `SMRT Analysis`_ (6) documentation + +9. Automated Tests +================== + +9.1. Unit Testing +----------------- + +The library shall have unit tests for all classes & components. + +9.2. Performance Testing +------------------------ + +Unit tests may evaluate performance requirements as desired. + +9.3. Regression Testing +----------------------- + +As its role is primarily in data I/O, pbbam has no "scientific quality/validity" +metrics that would indicate a regression. Instead, passing its unit tests and +end-to-end tests will indicate that a regression has not been introduced. + +These tests will be run after each check-in and nightly. + +10. Requirements Traceability Matrices +====================================== + +This section provides traces from requirements specified in PRD/DIR documents to the +requirements covered in this functional specification, and from these +functional requirements to corresponding Test Cases/Procedures. + +10.1. HPQC Functional Specifications +------------------------------------ + ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+-------------------------------------------+ +| **PBI_ID** | **Name** | **Description** | **Comment** | **Metric** | **Owner** | **PRD/DIR Path** | ++=============+===========================+===================================================+=============+============+===========+===========================================+ +| 5.1 | Query BAM data by | pbbam shall allow client applications to query | | | dbarnett | | +| | genomic region | data, limited to some genomic region of interest. | | | | | +| | | | | | | | ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+-------------------------------------------+ +| 5.2 | Query BAM data by | pbbam shall allow client applications to query | | | dbarnett | | +| | filter criteria | data, limited to some filter criteria (e.g. only | | | | | +| | | reads from ZMW hole number 200 with a read | | | | | +| | | quality of >0.5). | | | | | +| | | | | | | | ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+-------------------------------------------+ +| 5.3 | Write PacBio BAM data | pbbam shall be able to write files conforming to | | | dbarnett | | +| | | the `PacBio BAM`_ specifictation. | | | | | +| | | | | | | | ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+-------------------------------------------+ +| 5.4 | Create PacBio BAM index | Much of PacBio BAM data processing relies on the | | | dbarnett | | +| | file | presence of a `PacBio BAM index`_ file. pbbam | | | | | +| | | shall be able to generate this file type for a | | | | | +| | | `PacBio BAM`_ file. | | | | | +| | | | | | | | ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+-------------------------------------------+ + +10.2. Automated Tests Coverage +------------------------------ + ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ +| **FS Item** | **FS Item Title** | **Use Case Description** | **Test Case Name/ID** | ++=============+===========================+====================================================+==================================================================+ +| 5.1 | Query BAM data by | pbbam shall allow client applications to query | TODO | +| | genomic region | data, limited to some genomic region of interest. | | +| | | | | ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ +| 5.2 | Query BAM data by | pbbam shall allow client applications to query | TODO | +| | filter criteria | data, limited to some filter criteria (e.g. only | | +| | | reads from ZMW hole number 200 with a read | | +| | | quality of >0.5). | | +| | | | | ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ +| 5.3 | Write PacBio BAM data | pbbam shall be able to write files conforming to | TODO | +| | | the `PacBio BAM`_ specifictation. | | +| | | | | ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ +| 5.4 | Create PacBio BAM index | Much of PacBio BAM data processing relies on the | TODO | +| | file | presence of a `PacBio BAM index`_ file. pbbam | | +| | | shall be able to generate this file type for a | | +| | | `PacBio BAM`_ file. | | +| | | | | ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ + diff --git a/docs/specs/pbbam_structure.png b/docs/specs/pbbam_structure.png new file mode 100755 index 0000000000000000000000000000000000000000..40f50cf35456454a1da86f1bb49d7c0f43e80cce GIT binary patch literal 23521 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 UlC}|G%YDjF&-4cJ`u%7B1K`or&j0`b literal 0 HcmV?d00001 diff --git a/docs/specs/pbbam_updated_release3_2.rst b/docs/specs/pbbam_updated_release3_2.rst new file mode 100755 index 0000000..72d9b76 --- /dev/null +++ b/docs/specs/pbbam_updated_release3_2.rst @@ -0,0 +1,618 @@ +============================================================= +**Pbbam Core API Software Design & Functional Specification** +============================================================= +| *Version 0.2* +| *Pacific Biosciences Engineering Group* +| *Oct 17, 2016* + +1. Revision History +=================== + ++-------------+---------------+--------------------+---------------------------------+ +| **Date** | **Revision** | **Author(s)** | **Comments** | ++=============+===============+====================+=================================+ +| 01-29-2016 | 0.1 | Derek Barnett | Initial draft created | +| | | | | ++-------------+---------------+--------------------+---------------------------------+ +| 10-17-2016 | 0.2 | Derek Barnett | Added behavioral representation | +| | | | and structural representation | +| | | | diagram | ++-------------+---------------+--------------------+---------------------------------+ + +2. Introduction +=============== + +2.1. Document Specification Identifier +-------------------------------------- + ++-----------------------------------+------------------------------------------+ +| **Document Specification Prefix** | **Description** | ++===================================+==========================================+ +| FS\_SA\_PBBAM\_ | Functional spec for pbbam | ++-----------------------------------+------------------------------------------+ + +2.2. Purpose +------------ + +This document is intended to describe the requirements and interface of the pbbam +library, which provides functionality for creating, querying, and editing PacBio +BAM files and associated file formats. + +2.3. Scope of Document +---------------------- + +This document covers the expected usage of the pbbam library, as well as any +desired or required performance characteristics with respect to quality or speed. + +This document does not provide installation instructions or API documentation. + +2.4. Glossary of Terms +---------------------- + +The table below specifies only terms specific to this document, and skips +acronyms/terms that are specified in `Pacific Biosciences Software Glossary`_. + +.. _Pacific Biosciences Software Glossary: http://smrtanalysis-docs/pb_sw_glossary.html + ++------------------+-----------------------------------------------------------+ +| **Acronym/Term** | **Description** | ++==================+===========================================================+ +| API | Application Programming Interface - a set of routines, | +| | protocols, and tools for building software applications. | +| | In this document, this will consist of one or more | +| | cooperating libraries that specify data structures, | +| | methods, etc. for use within a target programming | +| | language. | ++------------------+-----------------------------------------------------------+ +| Client | An application that uses the library. | ++------------------+-----------------------------------------------------------+ +| I/O | Input/output of data. | ++------------------+-----------------------------------------------------------+ + +2.5. References +--------------- + ++-------------+------------------------------+--------------------------------------+ +| **Ref No.** | **Document Name, Link** | **Description** | ++=============+==============================+======================================+ +| (1) | `BAM format`_ | General SAM/BAM specification | ++-------------+------------------------------+--------------------------------------+ +| (2) | `PacBio BAM`_ | PacBio BAM specification | ++-------------+------------------------------+--------------------------------------+ +| (3) | `PacBio BAM index`_ | PacBio BAM index specification | ++-------------+------------------------------+--------------------------------------+ +| (4) | `DataSet XML`_ | PacBio DataSet XML specification | ++-------------+------------------------------+--------------------------------------+ +| (5) | `Software Style Guide`_ | PacBio coding standards | ++-------------+------------------------------+--------------------------------------+ +| (6) | `SMRT Analysis`_ | General SMRT Analysis infrastructure | ++-------------+------------------------------+--------------------------------------+ + +.. _BAM format: https://samtools.github.io/hts-specs/SAMv1.pdf +.. _PacBio BAM: http://pacbiofileformats.readthedocs.org/en/3.0/BAM.html +.. _PacBio BAM index: http://pacbiofileformats.readthedocs.org/en/3.0/PacBioBamIndex.html +.. _DataSet XML: https://github.com/PacificBiosciences/PacBioFileFormats/blob/3.0/DataSet.rst +.. _Software Style Guide: http://smrtanalysis-docs/_downloads/PBISoftwareStyleGuide.doc +.. _SMRT Analysis: http://smrtanalysis-docs/smrt_docs.html + +3. Software Overview +==================== + +3.1. Software Module Description +-------------------------------- + +As of the 3.0 release of SMRT Analysis, PacBio is embracing the industry standard +`BAM format`_ (1) for (both aligned and unaligned) basecall data files. We have +also formulated a BAM companion file format (.bam.pbi) enabling fast access to a +richer set of per-read information as well as compatibility for software built +around the legacy cmp.h5 format. + +The pbbam library provides components to create, query, & transform PacBio BAM +data: sequence files and their associated indices. This includes a core C++ +library as well as bindings for additional programming languages. + +3.2. Software Module Functional Capabilities +-------------------------------------------- + +The library must be able to read and write BAM files that conform to the +`PacBio BAM`_ specification (2). BAM records must be editable e.g. adding +alignment information. Random access must be supported, whether by genomic +region or by filtering record features. To this end, the library will be able to +read, write, and create associated index files - both the standard BAM index +(.bai) and the `PacBio BAM index`_ (.pbi) (3). In addition to working with +individual files, datasets of related BAM files will be supported. These are +described in a `DataSet XML`_ document. (4) + +3.3. User Characteristics +------------------------- + ++---------------------+--------------------------------------------------------+ +| **User Class/Role** | **User Knowledge and Skill Levels** | ++=====================+========================================================+ +| Developer | Competence in one or more programming languages | +| | supported (C++, R, Python, C#). No knowledge of | +| | molecular biology wet lab techniques required. | ++---------------------+--------------------------------------------------------+ + +3.4. User Operations and Practices +---------------------------------- + +Developer users will interact with the software by incorporating the library +into a client application. + +3.5. Operating Environment +-------------------------- + +The software is intended to be run in a Linux or OSX environment, with ideally 4 +or more cores. + +3.6. General Constraints +------------------------ + +Currently there are no constraints outside the operating environment and speed +requirements. In particular, as the library will be used for writing the BAM +files coming off a Sequel instrument, it should be able to keep pace. + +3.7. Assumptions and Dependencies +--------------------------------- + +Input routines for the library will expect to receive files that conform to the +`PacBio BAM`_ (2) or `DataSet XML`_ (4) specifications. + +The pbbam library depends on Boost, zlib, and htslib libraries. + +3.8. Other Software +------------------- + +Output PacBio BAMs will be compatible with the `PacBio BAM`_ specification (2) +and thus compatible with the general `BAM format`_ specification (1). This +ensures that a wide variety of downstream tools can interact with data files. + +The software uses `CMake`_ as its build system. + +The core C++ API relies on the following 3rd party components: + +* `zlib`_ +* `htslib`_ +* `Boost`_ (header-only modules) + +Wrapper APIs for additional languages (Python, R, C#) are generated by `SWIG`_. + +API documentation is generated via `Doxygen`_. + +.. _CMake: https://cmake.org/ +.. _zlib: http://www.zlib.net/ +.. _htslib: https://github.com/samtools/htslib +.. _Boost: http://www.boost.org/ +.. _SWIG: http://www.swig.org/ +.. _Doxygen: http://www.stack.nl/~dimitri/doxygen/ + +4. External Interfaces +====================== + +4.1. User Interfaces +-------------------- + +N/A + +4.2. Software Interfaces +------------------------ + +pbbam will require the following software: + +* `htslib`_ & `zlib`_ - provides low-level handling of compressed BAM data +* `Boost`_ - provides utility classes + +Incoming data from upstream components will be compliant with +PacBio BAM format - see `PacBio BAM`_ specification (2) for more detail. + +4.3. Hardware Interfaces +------------------------ + +N/A + +4.4. Communications Interfaces +------------------------------ + +N/A + +5. Functional Requirements +========================== + +5.1. Query BAM data by genomic region +------------------------------------- + +5.1.1. Description +~~~~~~~~~~~~~~~~~~ + +pbbam shall allow client applications to query data, limited to some genomic +region of interest. + +5.1.2. Inputs +~~~~~~~~~~~~~ + +* BAM file(s) or DataSet XML +* a standard index (.bai) for each source BAM file +* genomic interval (e.g. "chr1:1000-2000") + +5.1.3. Processing +~~~~~~~~~~~~~~~~~ + +Obtain an `htslib`_ "iterator" object for a given file and region. This will be +wrapped by pbbam to hide the low-level nature of this type, as well as handling +memory lifetime. + +5.1.4. Outputs +~~~~~~~~~~~~~~ + +Iterator providing access to individual BAM records from the input data sources, +which are aligned to the requested genomic interval. + +For example: + +.. code:: c++ + + GenomicIntervalQuery query(interval, dataset); + for (const BamRecord& record : query) { + // ... use record data ... + } + + +5.2. Query BAM data by filter criteria +-------------------------------------- + +5.2.1. Description +~~~~~~~~~~~~~~~~~~ + +pbbam shall allow client applications to query data, limited to some filter +criteria (e.g. only reads from ZMW hole number 200 with a read quality of >0.5). + +5.2.2. Inputs +~~~~~~~~~~~~~ + +* BAM file(s) or DataSet XML +* a `PacBio BAM index`_ (.pbi) for each source BAM file +* filters supported by data contained in the PBI + +5.2.3. Processing +~~~~~~~~~~~~~~~~~ + +Query PBI files(s) for records that match the provided filter criteria. Merge +contiguous runs of records into record blocks, to minimize seeks. Advancing the +iterator either reads the next read from the current block or seeks to the next +block and fetches the next record. + +5.2.4. Outputs +~~~~~~~~~~~~~~ + +Iterator providing access to individual BAM records from the input data sources, +which satisfy the requested filter criteria. + +For example: + +.. code:: c++ + + PbiFilterQuery query(filter, dataset); + for (const BamRecord& record : query) { + // ... do stuff ... + } + + +5.3. Write PacBio BAM data +-------------------------- + +5.3.1. Description +~~~~~~~~~~~~~~~~~~ + +pbbam shall be able to write `PacBio BAM`_ files conforming to the specification. + +5.3.2. Inputs +~~~~~~~~~~~~~ + +* filename +* header information +* BAM records + +5.3.3. Processing +~~~~~~~~~~~~~~~~~ + +Create file handle for the provided filename, output initial header information. +As records are passed in, write to file. Upon completion, flush any buffers and +close file handle. + +Multithreading, provided by `htslib`_, will be utilized where possible to speed +up the compression process - often then main bottleneck of BAM throughput. + +5.3.4. Outputs +~~~~~~~~~~~~~~ + +BAM file conforming to the `PacBio BAM`_ specification. + +5.4. Create PacBio BAM index file +--------------------------------- + +5.4.1. Description +~~~~~~~~~~~~~~~~~~ + +Much of PacBio BAM data processing relies on the presence of a `PacBio BAM index`_ +file. pbbam shall be able to generate this file type for a `PacBio BAM`_ file. + +5.4.2. Inputs +~~~~~~~~~~~~~ + +`PacBio BAM`_ file + +5.4.3. Processing +~~~~~~~~~~~~~~~~~ + +Read through the input BAM records, storing the values relevant to a PBI index. +At end of file, write the index contents to a file and close. + +5.4.4. Outputs +~~~~~~~~~~~~~~ + +`PacBio BAM index`_ file + +6. Non-Functional Requirements +============================== + +6.1. Performance Requirements +----------------------------- + +Since pbbam will be used to write all BAM files coming off a Sequel instrument, the +library must keep pace with data generation requirements. + +6.2. Safety Requirements +------------------------ + +N/A + +6.3. Security Requirements +-------------------------- + +N/A + +6.4. Quality Attributes +----------------------- + +6.4.1. Availability +~~~~~~~~~~~~~~~~~~~ + +The developed software shall meet the overall product availability requirements. + +6.4.2. Data Integrity +~~~~~~~~~~~~~~~~~~~~~ + +Inputs and outputs shall adhere to the PacBio BAM or DataSet XML specifications. +Files that do not meet this requirement will raise exceptions and will not be +accepted. + +6.4.3. Interoperability +~~~~~~~~~~~~~~~~~~~~~~~ + +Inputs and outputs shall adhere to the PacBio BAM or DataSet XML specifications. + +6.4.4. Reliability +~~~~~~~~~~~~~~~~~~ + +The developed software shall meet the overall product reliability requirements. + +6.4.5. Robustness +~~~~~~~~~~~~~~~~~ + +pbbam will raise exceptions upon encountering failure cases, allowing client +applications to recover or report the error to a UI. + +6.4.6. Usability +~~~~~~~~~~~~~~~~ + +pbbam shall have comprehensive API documentation, available both on- and offline. +Further documentation will be provided for installation, API usage tips, etc. + +Raised exceptions shall carry as much information as possible so that client +applications can respond with appropriate actions or display useful messages. + +6.4.7. Maintainability +~~~~~~~~~~~~~~~~~~~~~~ + +The source code of the software covered in this functional specification shall +adhere to the PacBio `Software Style Guide`_ (9) work instruction, to guarantee +high quality of code that facilitates maintainability. + +6.4.8. Customizability +~~~~~~~~~~~~~~~~~~~~~~ + +N/A + +6.4.9. Compatibility +~~~~~~~~~~~~~~~~~~~~ + +pbbam shall support backward compatibility of the API and BAM format versions +in order not to break existing clients. + +6.5. Business Rules +------------------- + +N/A + +6.6. Compliance Requirements +---------------------------- + +N/A + +6.7. Alarms and Error Handling +------------------------------ + +Raised exceptions shall carry as much information as possible so that client +applications can respond with appropriate actions or display useful messages. + +6.8. Persistence Requirements +----------------------------- + +pbbam software requires no persistent storage outside of availability of input +and output during analysis. + +6.9. Installation and Upgrade +----------------------------- + +Installation and Upgrade of this software will be handled as part of the SMRT +Analysis subsystem. See `SMRT Analysis`_ (6) specifications for more detail. + +Additionally, the library may be built independently, either from internal +version control (Perforce) or from the public-facing Github repository. In +either case, `CMake`_ is used to drive the build process. + +6.10. Administration and Maintenance +------------------------------------ + +N/A + +6.11. User Documentation +------------------------ + +pbbam shall have comprehensive API documentation, available both on- and offline. +Further documentation will be provided for installation, API usage tips, etc. + +The "offline" API documentation may be built directly from the source code, using +`Doxygen`_. Online documentation will be generated via a continuous integration +server, thus ensuring it is always pointing to the current codebase. + +7. High Level Design +==================== + +7.1. Top Level Context +---------------------- + +The pbbam library is intended to be linked in with client applications, +providing programmatic access to data files. + +7.2. Use Cases +-------------- + +Primary use cases for pbbam include: + +* BAM file creation +* BAM file query - iterable access to various subsets of data + +8. Detailed Design +================== + +8.1. Structural Representation +------------------------------ + +.. image:: ./pbbam_structure.png + +8.2. Behavioral Representation +------------------------------ + +The typical access pattern involves a client query against BAM data, optionally +described in DataSet XML. The query may involve some number of filter criteria. + +pbbam queries the associated index files (*.pbi) to pre-determine which records +pass filtering criteria and where they reside on disk. The client code is given +an iterable object, such that each iteration of the main access loop returns a +valid BAM record for analysis, modification, etc. + +8.3. Information Storage +------------------------ + +pbbam software requires no persistent storage outside of availability of input +and output during analysis. + +8.4. Technology Overview +------------------------ + +pbbam is implemented in C++-11 and should perform as designed on any UNIX-like +operating system (Linux distributions, Apple OSX, etc.). + +8.5. SOUP Components +-------------------- + +pbbam utilizes CMake for its build system. The C++ library uses the following +3rd-party software components: `Boost`_, `htslib`_, & `zlib`_. Wrappers for additional +languages are generated using SWIG. + +8.6. Deployment and Configuration +--------------------------------- + +Please refer to `SMRT Analysis`_ (6) documentation + +9. Automated Tests +================== + +9.1. Unit Testing +----------------- + +The library shall have unit tests for all classes & components. + +9.2. Performance Testing +------------------------ + +Unit tests may evaluate performance requirements as desired. + +9.3. Regression Testing +----------------------- + +As its role is primarily in data I/O, pbbam has no "scientific quality/validity" +metrics that would indicate a regression. Instead, passing its unit tests and +end-to-end tests will indicate that a regression has not been introduced. + +These tests will be run after each check-in and nightly. + +10. Requirements Traceability Matrices +====================================== + +This section provides traces from requirements specified in PRD/DIR documents to the +requirements covered in this functional specification, and from these +functional requirements to corresponding Test Cases/Procedures. + +10.1. HPQC Functional Specifications +------------------------------------ + ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+--------------------------------------------------+ +| **PBI_ID** | **Name** | **Description** | **Comment** | **Metric** | **Owner** | **PRD/DIR Path** | ++=============+===========================+===================================================+=============+============+===========+==================================================+ +| 5.1 | Query BAM data by | pbbam shall allow client applications to query | | Yes | dbarnett | \\DIR\\Functionality\\Software\Common\APIs\\ | +| | genomic region | data, limited to some genomic region of interest. | | | | Software shall provide an API to allow 3rd | +| | | | | | | party software to extract all run information | +| | | | | | | including summary reports and locations | ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+--------------------------------------------------+ +| 5.2 | Query BAM data by | pbbam shall allow client applications to query | | Yes | dbarnett | \\DIR\\Functionality\\Software\Common\APIs\\ | +| | filter criteria | data, limited to some filter criteria (e.g. only | | | | Software shall provide an API to allow 3rd | +| | | reads from ZMW hole number 200 with a read | | | | party software to extract all run information | +| | | quality of >0.5). | | | | including summary reports and locations | ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+--------------------------------------------------+ +| 5.3 | Write PacBio BAM data | pbbam shall be able to write files conforming to | | Yes | dbarnett | \\DIR\\Functionality\\Software\\PostProcessing\\ | +| | | the `PacBio BAM`_ specification. | | | | Software shall provide base files including | +| | | | | | | kinetic information in industry standard format | +| | | | | | | such as SAM/BAM using current specifications | ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+--------------------------------------------------+ +| 5.4 | Create PacBio BAM index | Much of PacBio BAM data processing relies on the | | Yes | dbarnett | \\DIR\\Functionality\\Software\\PostProcessing\\ | +| | file | presence of a `PacBio BAM index`_ file. pbbam | | | | Software shall provide base files including | +| | | shall be able to generate this file type for a | | | | kinetic information in industry standard format | +| | | `PacBio BAM`_ file. | | | | such as SAM/BAM using current specifications | ++-------------+---------------------------+---------------------------------------------------+-------------+------------+-----------+--------------------------------------------------+ + +10.2. Automated Tests Coverage +------------------------------ + ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ +| **FS Item** | **FS Item Title** | **Use Case Description** | **Test Case Name/ID** | ++=============+===========================+====================================================+==================================================================+ +| 5.1 | Query BAM data by | pbbam shall allow client applications to query | See section 9.1. Unit Testing. | +| | genomic region | data, limited to some genomic region of interest. | | ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ +| 5.2 | Query BAM data by | pbbam shall allow client applications to query | See section 9.1. Unit Testing. | +| | filter criteria | data, limited to some filter criteria (e.g. only | | +| | | reads from ZMW hole number 200 with a read | | +| | | quality of >0.5). | | ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ +| 5.3 | Write PacBio BAM data | pbbam shall be able to write files conforming to | See section 9.1. Unit Testing. | +| | | the `PacBio BAM`_ specification. | | ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ +| 5.4 | Create PacBio BAM index | Much of PacBio BAM data processing relies on the | See section 9.1. Unit Testing. | +| | file | presence of a `PacBio BAM index`_ file. pbbam | | +| | | shall be able to generate this file type for a | | +| | | `PacBio BAM`_ file. | | ++-------------+---------------------------+----------------------------------------------------+------------------------------------------------------------------+ + diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 0000000..35fd9ed --- /dev/null +++ b/include/meson.build @@ -0,0 +1,165 @@ +########### +# headers # +########### + +if not meson.is_subproject() + install_headers( + files([ + 'pbbam/Accuracy.h', + 'pbbam/AlignmentPrinter.h', + 'pbbam/BaiIndexCache.h', + 'pbbam/BaiIndexedBamReader.h', + 'pbbam/BamFile.h', + 'pbbam/BamFileMerger.h', + 'pbbam/BamHeader.h', + 'pbbam/BamReader.h', + 'pbbam/BamRecord.h', + 'pbbam/BamRecordBuilder.h', + 'pbbam/BamRecordImpl.h', + 'pbbam/BamRecordTag.h', + 'pbbam/BamRecordView.h', + 'pbbam/BamTagCodec.h', + 'pbbam/BamWriter.h', + 'pbbam/BarcodeQuery.h', + 'pbbam/BgzipFastaWriter.h', + 'pbbam/BgzipFastqWriter.h', + 'pbbam/BgzipWriter.h', + 'pbbam/Cigar.h', + 'pbbam/CigarOperation.h', + 'pbbam/ClipType.h', + 'pbbam/Compare.h', + 'pbbam/CompositeBamReader.h', + 'pbbam/CompositeFastaReader.h', + 'pbbam/Config.h', + 'pbbam/DataSet.h', + 'pbbam/DataSetTypes.h', + 'pbbam/DataSetXsd.h', + 'pbbam/EntireFileQuery.h', + 'pbbam/FaiIndex.h', + 'pbbam/FastaCache.h', + 'pbbam/FastaReader.h', + 'pbbam/FastaSequence.h', + 'pbbam/FastaSequenceQuery.h', + 'pbbam/FastaWriter.h', + 'pbbam/FastqReader.h', + 'pbbam/FastqSequence.h', + 'pbbam/FastqWriter.h', + 'pbbam/FormatUtils.h', + 'pbbam/FrameEncodingType.h', + 'pbbam/Frames.h', + 'pbbam/GenomicInterval.h', + 'pbbam/GenomicIntervalQuery.h', + 'pbbam/IFastaWriter.h', + 'pbbam/IFastqWriter.h', + 'pbbam/IndexedBamWriter.h', + 'pbbam/IndexedFastaReader.h', + 'pbbam/IndexedFastqReader.h', + 'pbbam/Interval.h', + 'pbbam/IRecordWriter.h', + 'pbbam/LocalContextFlags.h', + 'pbbam/MD5.h', + 'pbbam/MoveAppend.h', + 'pbbam/Orientation.h', + 'pbbam/PbiBasicTypes.h', + 'pbbam/PbiBuilder.h', + 'pbbam/PbiFile.h', + 'pbbam/PbiFilter.h', + 'pbbam/PbiFilterQuery.h', + 'pbbam/PbiFilterTypes.h', + 'pbbam/PbiIndexedBamReader.h', + 'pbbam/PbiRawData.h', + 'pbbam/Position.h', + 'pbbam/ProgramInfo.h', + 'pbbam/PulseBehavior.h', + 'pbbam/PulseExclusionReason.h', + 'pbbam/QNameQuery.h', + 'pbbam/QualityValue.h', + 'pbbam/QualityValues.h', + 'pbbam/ReadAccuracyQuery.h', + 'pbbam/ReadGroupInfo.h', + 'pbbam/RecordType.h', + 'pbbam/SamTagCodec.h', + 'pbbam/SamWriter.h', + 'pbbam/SequenceInfo.h', + 'pbbam/SNR.h', + 'pbbam/Strand.h', + 'pbbam/StringUtilities.h', + 'pbbam/SubreadLengthQuery.h', + 'pbbam/Tag.h', + 'pbbam/TagCollection.h', + 'pbbam/TextFileReader.h', + 'pbbam/TextFileWriter.h', + 'pbbam/Unused.h', + 'pbbam/Validator.h', + 'pbbam/ZmwGroupQuery.h', + 'pbbam/ZmwQuery.h', + 'pbbam/ZmwType.h', + 'pbbam/ZmwTypeMap.h']), + subdir : 'pbbam') + + install_headers( + files([ + 'pbbam/bed/BedReader.h', + 'pbbam/bed/BedWriter.h']), + subdir : 'pbbam/bed') + + install_headers( + files([ + 'pbbam/ccs/CCSHeader.h', + 'pbbam/ccs/CCSPbiBuilder.h', + 'pbbam/ccs/CCSRecord.h', + 'pbbam/ccs/CCSRecordFormat.h', + 'pbbam/ccs/CCSRecordReader.h', + 'pbbam/ccs/CCSRecordWriter.h']), + subdir : 'pbbam/ccs') + + install_headers( + files([ + 'pbbam/exception/BundleChemistryMappingException.h', + 'pbbam/exception/InvalidSequencingChemistryException.h', + 'pbbam/exception/ValidationException.h']), + subdir : 'pbbam/exception') + + install_headers( + files([ + 'pbbam/internal/Compare.inl', + 'pbbam/internal/CompositeBamReader.inl', + 'pbbam/internal/DataSetBaseTypes.h', + 'pbbam/internal/DataSetElement.h', + 'pbbam/internal/DataSetElement.inl', + 'pbbam/internal/PbiBasicTypes.inl', + 'pbbam/internal/PbiFilter.inl', + 'pbbam/internal/PbiFilterTypes.inl', + 'pbbam/internal/QueryBase.h', + 'pbbam/internal/QueryBase.inl']), + subdir : 'pbbam/internal') + + install_headers( + files([ + 'pbbam/vcf/VcfVariant.h', + 'pbbam/vcf/VcfFile.h', + 'pbbam/vcf/VcfFormat.h', + 'pbbam/vcf/VcfHeader.h', + 'pbbam/vcf/VcfHeaderTypes.h', + 'pbbam/vcf/VcfReader.h', + 'pbbam/vcf/VcfSort.h', + 'pbbam/vcf/VcfQuery.h', + 'pbbam/vcf/VcfWriter.h']), + subdir : 'pbbam/vcf') + + install_headers( + files([ + 'pbbam/virtual/VirtualPolymeraseBamRecord.h', + 'pbbam/virtual/VirtualPolymeraseCompositeReader.h', + 'pbbam/virtual/VirtualPolymeraseReader.h', + 'pbbam/virtual/VirtualRegion.h', + 'pbbam/virtual/VirtualRegionType.h', + 'pbbam/virtual/VirtualRegionTypeMap.h', + 'pbbam/virtual/VirtualZmwBamRecord.h', + 'pbbam/virtual/WhitelistedZmwReadStitcher.h', + 'pbbam/virtual/ZmwReadStitcher.h', + 'pbbam/virtual/ZmwWhitelistVirtualReader.h']), + subdir : 'pbbam/virtual') +endif + +pbbam_include_directories = include_directories('.') diff --git a/include/pbbam/Accuracy.h b/include/pbbam/Accuracy.h new file mode 100644 index 0000000..f5bf7b8 --- /dev/null +++ b/include/pbbam/Accuracy.h @@ -0,0 +1,22 @@ +// File Description +/// \file Accuracy.h +/// \brief Defines the Accuracy class. +// +// Author: Derek Barnett + +#ifndef ACCURACY_H +#define ACCURACY_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +using Accuracy PBBAM_DEPRECATED = Data::Accuracy; + +} // namespace BAM +} // namespace PacBio + +#endif // ACCURACY_H diff --git a/include/pbbam/AlignmentPrinter.h b/include/pbbam/AlignmentPrinter.h new file mode 100644 index 0000000..264b193 --- /dev/null +++ b/include/pbbam/AlignmentPrinter.h @@ -0,0 +1,71 @@ +// File Description +/// \file AlignmentPrinter.h +/// \brief Defines the AlignmentPrinter class. +// +// Author: Armin Töpfer + +#ifndef ALIGNMENTPRINTER_H +#define ALIGNMENTPRINTER_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/BamRecord.h" +#include "pbbam/IndexedFastaReader.h" +#include "pbbam/Orientation.h" + +namespace PacBio { +namespace BAM { + +class BamRecord; + +/// \brief The AlignmentPrinter class "pretty-prints" an alignment with respect +/// to its associated reference sequence. +/// +/// Example output: +/// \verbinclude plaintext/AlignmentPrinterOutput.txt +/// +class AlignmentPrinter +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// Constructs the alignment printer with an associated FASTA file reader. + /// + /// \param[in] ifr FASTA reader + /// + /// \throws std::runtime_error if FASTA file cannot be opened for reading. + /// + AlignmentPrinter(const IndexedFastaReader& ifr); + + /// \} + +public: + /// \name Printing + /// \{ + + /// Pretty-prints an aligned BamRecord to std::string. + /// + /// \note The current implementation includes ANSI escape sequences for + /// coloring terminal output. Future versions of this method will + /// likely make this optional. + /// + /// \returns formatted string containing the alignment and summary + /// information + /// + std::string Print(const BamRecord& record, + const Orientation orientation = Orientation::GENOMIC); + + /// \} + +private: + std::unique_ptr ifr_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ALIGNMENTPRINTER_H diff --git a/include/pbbam/BaiIndexCache.h b/include/pbbam/BaiIndexCache.h new file mode 100644 index 0000000..65efda5 --- /dev/null +++ b/include/pbbam/BaiIndexCache.h @@ -0,0 +1,60 @@ +// File Description +/// \file BaiIndexCache.h +/// \brief Defines the BaiIndexCache class. +// +// Author: Derek Barnett + +#ifndef BAIINDEXCACHE_H +#define BAIINDEXCACHE_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +#include "pbbam/Position.h" + +namespace PacBio { +namespace BAM { + +class BamFile; +class DataSet; + +/// +/// \brief Caches contents of *.bai file for re-use by multiple readers. +/// +class BaiIndexCacheData +{ +public: + explicit BaiIndexCacheData(const BamFile& bamFile); + explicit BaiIndexCacheData(const std::string& bamFilename); + + ~BaiIndexCacheData(); + + /// \note This is very much an internal method and should not be considered + /// public API. Exposed here only because of implementation details + /// (definition of htslib-related custom deleters) and may be removed. + /// + /// \note Does not own the returned pointer; caller is responsible. + /// + hts_itr_t* IteratorForInterval(const int32_t refId, const Position start, + const Position stop) const; + +private: + struct BaiIndexCacheDataPrivate; + std::unique_ptr d_; +}; + +using BaiIndexCache = std::shared_ptr>>; + +BaiIndexCache MakeBaiIndexCache(const DataSet& dataset); +BaiIndexCache MakeBaiIndexCache(const std::vector& bamFiles); +BaiIndexCache MakeBaiIndexCache(const BamFile& bamFile); + +} // namespace BAM +} // namespace PacBio + +#endif // BAIINDEXCACHE_H diff --git a/include/pbbam/BaiIndexedBamReader.h b/include/pbbam/BaiIndexedBamReader.h new file mode 100644 index 0000000..8745d85 --- /dev/null +++ b/include/pbbam/BaiIndexedBamReader.h @@ -0,0 +1,115 @@ +// File Description +/// \file BaiIndexedBamReader.h +/// \brief Defines the BaiIndexedBamReader class. +// +// Author: Derek Barnett + +#ifndef BAIINDEXEDBAMREADER_H +#define BAIINDEXEDBAMREADER_H + +#include "pbbam/Config.h" + +#include + +#include + +#include "pbbam/BaiIndexCache.h" +#include "pbbam/BamFile.h" +#include "pbbam/BamReader.h" +#include "pbbam/GenomicInterval.h" + +namespace PacBio { +namespace BAM { + +/// \brief The BaiIndexedBamReader class provides read-only iteration over %BAM +/// records, bounded by a particular genomic interval. +/// +/// The SAM/BAM standard index (*.bai) is used to allow random-access operations. +/// +class PBBAM_EXPORT BaiIndexedBamReader : public BamReader +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Constructs %BAM reader, that can be queried on genomic interval. + /// + /// \param filename input %BAM filename + /// + /// \throws std::runtime_error if either file (*.bam or *.bai) fails to open + /// for reading, or if the interval is invalid + /// + explicit BaiIndexedBamReader(std::string filename); + BaiIndexedBamReader(std::string filename, const std::shared_ptr& index); + + /// \brief Constructs %BAM reader, that can be queried on genomic interval. + /// + /// \param[in] bamFile input BamFile object + /// + /// \throws std::runtime_error if either file (*.bam or *.bai) fails to open + /// for reading, or if the interval is invalid + /// + explicit BaiIndexedBamReader(BamFile bamFile); + BaiIndexedBamReader(BamFile bamFile, const std::shared_ptr& index); + + /// \brief Constructs %BAM reader, bounded by a genomic interval. + /// + /// All reads that overlap the interval will be available. + /// + /// \param[in] interval iteration will be bounded by this GenomicInterval. + /// \param[in] filename input %BAM filename + /// + /// \throws std::runtime_error if either file (*.bam or *.bai) fails to open + /// for reading, or if the interval is invalid + /// + BaiIndexedBamReader(const GenomicInterval& interval, std::string filename); + BaiIndexedBamReader(const GenomicInterval& interval, std::string filename, + const std::shared_ptr& index); + + /// \brief Constructs %BAM reader, bounded by a genomic interval. + /// + /// All reads that overlap the interval will be available. + /// + /// \param[in] interval iteration will be bounded by this GenomicInterval. + /// \param[in] bamFile input BamFile object + /// + /// \throws std::runtime_error if either file (*.bam or *.bai) fails to open + /// for reading, or if the interval is invalid + /// + BaiIndexedBamReader(const GenomicInterval& interval, BamFile bamFile); + BaiIndexedBamReader(const GenomicInterval& interval, BamFile bamFile, + const std::shared_ptr& index); + + /// \} + +public: + /// \name Random-Access + /// \{ + + /// \returns the underlying BamFile + const BamFile& File() const; + + /// \returns the current GenomicInterval in use by this reader + const GenomicInterval& Interval() const; + + /// \brief Sets a new genomic interval on the reader. + /// + /// \param[in] interval + /// \returns reference to this reader + /// + BaiIndexedBamReader& Interval(const GenomicInterval& interval); + + /// \} + +protected: + int ReadRawData(BGZF* bgzf, bam1_t* b) override; + +private: + class BaiIndexedBamReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAIINDEXEDBAMREADER_H diff --git a/include/pbbam/BamFile.h b/include/pbbam/BamFile.h new file mode 100644 index 0000000..4748f2f --- /dev/null +++ b/include/pbbam/BamFile.h @@ -0,0 +1,183 @@ +// File Description +/// \file BamFile.h +/// \brief Defines the BamFile class. +// +// Author: Derek Barnett + +#ifndef BAMFILE_H +#define BAMFILE_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/BamHeader.h" + +namespace PacBio { +namespace BAM { + +/// \brief The BamFile class represents a %BAM file. +/// +/// It provides access to header metadata and methods for finding/creating +/// associated index files. +/// +class PBBAM_EXPORT BamFile +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates a BamFile object on the provided \p filename & + /// loads header information. + /// + /// \param[in] filename %BAM filename + /// \throws std::exception on failure to open %BAM file for reading + /// + BamFile(std::string filename); + + BamFile(const BamFile& other); + BamFile(BamFile&& other) noexcept; + BamFile& operator=(const BamFile& other); + BamFile& operator=(BamFile&& other) noexcept; + ~BamFile(); + + /// \} + +public: + /// \name Index & Filename Methods + /// \{ + + /// \brief Creates a ".pbi" file for this %BAM file. + /// + /// \note Existing index file will be overwritten. Use + /// EnsurePacBioIndexExists() if this is not desired. + /// + /// \throws if PBI file could not be properly created and/or + /// written to disk + /// + void CreatePacBioIndex() const; + + /// \brief Creates a ".bai" file for this %BAM file. + /// + /// \note Existing index file will be overwritten. Use + /// EnsureStandardIndexExists() if this is not desired. + /// + /// \throws if BAI file could not be properly created (e.g. this + /// %BAM is not coordinate-sorted) or could not be written to disk + /// + void CreateStandardIndex() const; + + /// \brief Creates a ".pbi" file if one does not exist or is older than its + /// %BAM file. + /// + /// Equivalent to: + /// \code{.cpp} + /// if (!file.PacBioIndexExists()) + /// file.CreatePacBioIndex(); + /// \endcode + /// + /// \note As of v0.4.02+, no timestamp check is performed. Previously we requr + /// with an additional timestamp check. + /// + /// \throws if PBI file could not be properly created and/or + /// written to disk + /// + void EnsurePacBioIndexExists() const; + + /// \brief Creates a ".bai" file if one does not exist or is older than its + /// %BAM file. + /// + /// Equivalent to: + /// \code{.cpp} + /// if (!file.StandardIndexExists()) + /// file.CreateStandardIndex(); + /// \endcode + /// + /// \note As of v0.4.2, no timestamp check is performed. + /// + /// \throws if BAI file could not be properly created (e.g. this + /// %BAM is not coordinate-sorted) or could not be written to disk + /// + void EnsureStandardIndexExists() const; + + /// \returns %BAM filename + const std::string& Filename() const; + + /// \returns true if %BAM file has EOF marker (empty BGZF block). Streamed + /// input (filename: "-") + bool HasEOF() const; + + /// \returns true if ".pbi" exists and is newer than this %BAM file. + bool PacBioIndexExists() const; + + /// \returns filename of %PacBio index file (".pbi") + /// \note No guarantee is made on the existence of this file. + /// This method simply returns the expected filename. + std::string PacBioIndexFilename() const; + + /// \returns true if ".pbi" has a more recent timestamp than this file + bool PacBioIndexIsNewer() const; + + /// \returns true if ".bai" exists + bool StandardIndexExists() const; + + /// \note No guarantee is made on the existence of this file. + /// This method simply returns the expected filename. + std::string StandardIndexFilename() const; + + /// \returns true if ".bai" has a more recent timestamp than this file + bool StandardIndexIsNewer() const; + + /// \} + +public: + /// \name File Header Data + /// \{ + + /// \returns true if header metadata has this reference name + bool HasReference(const std::string& name) const; + + /// \returns const reference to BamHeader containing the file's metadata + const BamHeader& Header() const; + + /// \returns true if file is a %PacBio %BAM file (i.e. has non-empty version + /// associated with header "pb" tag) + bool IsPacBioBAM() const; + + /// \returns ID for reference \p name (can be used for e.g. + /// GenomicIntervalQuery), or -1 if not found + int ReferenceId(const std::string& name) const; + + /// \return name of reference matching \p id, empty string if not found + std::string ReferenceName(const int id) const; + + /// \returns length of requested reference \p name. 0 if not found + uint32_t ReferenceLength(const std::string& name) const; + + /// \returns length of requested reference \p id. 0 if not found + uint32_t ReferenceLength(const int id) const; + + /// \} + +public: + /// \name Additional Attributes + /// \{ + + /// \returns virtual offset of first alignment. Intended mostly for internal + /// use. Note that this is a BGZF \b virtual offset, not a + /// 'normal' file position. + /// + int64_t FirstAlignmentOffset() const; + + /// \} + +private: + class BamFilePrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMFILE_H diff --git a/include/pbbam/BamFileMerger.h b/include/pbbam/BamFileMerger.h new file mode 100644 index 0000000..e19821a --- /dev/null +++ b/include/pbbam/BamFileMerger.h @@ -0,0 +1,61 @@ +// Author: Derek Barnett + +#ifndef BAMFILEMERGER_H +#define BAMFILEMERGER_H + +#include "pbbam/Config.h" + +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +class DataSet; +class IRecordWriter; + +class BamFileMerger +{ +public: + /// \brief Runs merger on BAM files. + /// + /// When this function exits, a merged BAM (and optional PBI) will have been + /// written and closed. + /// + /// \param[in] bamFilenames input filenames + /// \param[in] outputFilename resulting BAM output + /// \param[in] createPbi if true, creates a PBI alongside output BAM + /// \param[in] pgInfo allows client applications to add its @PG entry to merged header + /// + /// \throws std::runtime_error if any any errors encountered while reading or writing + /// + static void Merge(const std::vector& bamFilenames, + const std::string& outputFilename, bool createPbi = true, + const ProgramInfo& pgInfo = ProgramInfo{}); + + /// \brief Runs merger on a dataset, applying any supplied filters. + /// + /// When this function exits, a merged BAM (and optional PBI) will have been + /// written and closed. + /// + /// \param[in] dataset provides input filenames & filters + /// \param[in] outputFilename resulting BAM output + /// \param[in] createPbi if true, creates a PBI alongside output BAM + /// \param[in] pgInfo allows client applications to add its @PG entry to merged header + /// + /// \throws std::runtime_error if any any errors encountered while reading or writing + /// + static void Merge(const PacBio::BAM::DataSet& dataset, const std::string& outputFilename, + bool createPbi = true, const ProgramInfo& pgInfo = ProgramInfo{}); + + static void Merge(const std::vector& bamFilenames, IRecordWriter& writer); + + static void Merge(const PacBio::BAM::DataSet& dataset, IRecordWriter& writer); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMFILEMERGER_H diff --git a/include/pbbam/BamHeader.h b/include/pbbam/BamHeader.h new file mode 100644 index 0000000..4e96783 --- /dev/null +++ b/include/pbbam/BamHeader.h @@ -0,0 +1,384 @@ +// File Description +/// \file BamHeader.h +/// \brief Defines the BamHeader class. +// +// Author: Derek Barnett + +#ifndef BAMHEADER_H +#define BAMHEADER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include +#include + +#include "pbbam/ProgramInfo.h" +#include "pbbam/ReadGroupInfo.h" +#include "pbbam/SequenceInfo.h" + +namespace PacBio { +namespace BAM { + +/// \brief The BamHeader class represents the header section of the %BAM file. +/// +/// It provides metadata about the file including file version, reference +/// sequences, read groups, comments, etc. +/// +/// A BamHeader may be fetched from a BamFile to view an existing file's +/// metadata. Or one may be created/edited for use with writing to a new file +/// (via BamWriter). +/// +/// \note A particular BamHeader is likely to be re-used in lots of places +/// throughout the library, for read-only purposes. For this reason, even +/// though a BamHeader may be returned by value, it is essentially a thin +/// wrapper for a shared-pointer to the actual data. This means, though, +/// that if you need to edit an existing BamHeader for use with a +/// BamWriter, please consider using BamHeader::DeepCopy. Otherwise any +/// modifications will affect all BamHeaders that are sharing its +/// underlying data. +/// +class PBBAM_EXPORT BamHeader +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// + /// \brief Creates a BamHeader from SAM-formatted text + /// \param samHeaderText + /// + BamHeader(const std::string& samHeaderText); + + BamHeader(); + + /// \brief Detaches underlying data from the shared-pointer, returning a + /// independent copy of the header contents. + /// + /// This ensures that any modifications to the newly returned BamHeader do + /// not affect other BamHeader objects that were sharing its underlying data. + /// + BamHeader DeepCopy() const; + + /// \} + +public: + /// \name Operators + /// \{ + + /// \brief Merges another header with this one. + /// + /// Headers must be compatible for merging. This means that their Version, + /// SortOrder, PacBioBamVersion (and in the case of aligned BAM data, + /// Sequences) must all match. If not, an exception will be thrown. + /// + /// \param[in] other header to merge with this one + /// \returns reference to this header + /// + /// \throws std::runtime_error if the headers are not compatible + /// + BamHeader& operator+=(const BamHeader& other); + + /// \brief Creates a new, merged header. + /// + /// Headers must be compatible for merging. This means that their Version, + /// SortOrder, PacBioBamVersion (and in the case of aligned BAM data, + /// Sequences) must all match. If not, an exception will be thrown. + /// + /// Both original headers (this header and \p other) will not be modified. + /// + /// \param[in] other header to merge with this one + /// \returns merged header + /// + /// \throws std::runtime_error if the headers are not compatible + /// + BamHeader operator+(const BamHeader& other) const; + + /// \} + +public: + /// \name General Attributes + /// \{ + + /// \returns the %PacBio %BAM version number (\@HD:pb) + /// + /// \note This is different from the SAM/BAM version number + /// \sa BamHeader::Version. + /// + std::string PacBioBamVersion() const; + + /// \returns the sort order used + /// + /// Valid values: "unknown", "unsorted", "queryname", or "coordinate" + /// + std::string SortOrder() const; + + /// \returns the SAM/BAM version number (\@HD:VN) + /// + /// \note This is different from the %PacBio %BAM version number + /// \sa BamHeader::PacBioBamVersion + /// + std::string Version() const; + + /// \} + +public: + /// \name Read Groups + /// \{ + + /// \returns true if the header contains a read group with \p id (\@RG:ID) + bool HasReadGroup(const std::string& id) const; + + /// \returns a ReadGroupInfo object representing the read group matching + /// \p id (\@RG:ID) + /// \throws std::runtime_error if \p id is unknown + /// + ReadGroupInfo ReadGroup(const std::string& id) const; + + /// \returns vector of read group IDs listed in this header + std::vector ReadGroupIds() const; + + /// \returns vector of ReadGroupInfo objects, representing all read groups + /// listed in this header + /// + std::vector ReadGroups() const; + + /// \} + +public: + /// \name Sequences + /// \{ + + /// \returns true if header contains a sequence with \p name (\@SQ:SN) + bool HasSequence(const std::string& name) const; + + /// \returns number of sequences (\@SQ entries) stored in this header + size_t NumSequences() const; + + /// \returns numeric ID for sequence matching \p name (\@SQ:SN) + /// + /// This is the numeric ID used elsewhere throughout the API. + /// + /// \throws std::runtime_error if \p name is unknown + /// \sa BamReader::ReferenceId, PbiReferenceIdFilter, + /// PbiRawMappedData::tId_ + /// + int32_t SequenceId(const std::string& name) const; + + /// \returns the length of the sequence (\@SQ:LN, e.g. chromosome length) at + /// index \p id + /// + /// \sa SequenceInfo::Length, BamHeader::SequenceId + /// + std::string SequenceLength(const int32_t id) const; + + /// \returns the name of the sequence (\@SQ:SN) at index \p id + /// + /// \sa SequenceInfo::Name, BamHeader::SequenceId + /// + std::string SequenceName(const int32_t id) const; + + /// \returns vector of sequence names (\@SQ:SN) stored in this header + /// + /// Position in the vector is equivalent to SequenceId. + /// + std::vector SequenceNames() const; + + /// \returns SequenceInfo object at index \p id + /// + /// \throws std::out_of_range if \p is an invalid or unknown index + /// \sa BamHeader::SequenceId + /// + SequenceInfo Sequence(const int32_t id) const; + + /// \returns SequenceInfo for the sequence matching \p name + SequenceInfo Sequence(const std::string& name) const; + + /// \returns vector of SequenceInfo objects representing the sequences + /// (\@SQ entries) stored in this header + /// + std::vector Sequences() const; + + /// \} + +public: + /// \name Programs + /// \{ + + /// \returns true if this header contains a program entry with ID (\@PG:ID) + /// matching \p id + /// + bool HasProgram(const std::string& id) const; + + /// \returns ProgramInfo object for the program entry matching \p id + /// \throws std::runtime_error if \p id is unknown + /// + ProgramInfo Program(const std::string& id) const; + + /// \returns vector of program IDs (\@PG:ID) + std::vector ProgramIds() const; + + /// \returns vector of ProgramInfo objects representing program entries + /// (\@PG) stored in this heder + /// + std::vector Programs() const; + + /// \} + +public: + /// \name Comments + /// \{ + + /// \returns vector of comment (\@CO) strings + std::vector Comments() const; + + /// \} + +public: + /// \name Conversion Methods + /// \{ + + /// \returns SAM-header-formatted string representing this header's data + std::string ToSam() const; + + /// \} + +public: + /// \name General Attributes + /// \{ + + /// \brief Sets this header's PacBioBAM version number (\@HD:pb). + /// + /// \returns reference to this object + /// \throws std::runtime_error if version number cannot be parsed or + /// is less than the minimum version allowed. + /// + BamHeader& PacBioBamVersion(const std::string& version); + + /// \brief Sets this header's sort order label (\@HD:SO). + /// + /// Valid values: "unknown", "unsorted", "queryname", or "coordinate" + /// + /// \returns reference to this object + /// + BamHeader& SortOrder(std::string order); + + /// \brief Sets this header's SAM/BAM version number (\@HD:VN). + /// + /// \returns reference to this object + /// + BamHeader& Version(std::string version); + + /// \} + +public: + /// \name Read Groups + /// \{ + + /// \brief Appends a read group entry (\@RG) to this header. + /// + /// \returns reference to this object + /// + BamHeader& AddReadGroup(ReadGroupInfo readGroup); + + /// \brief Removes all read group entries from this header. + /// + /// \returns reference to this object + /// + BamHeader& ClearReadGroups(); + + /// \brief Replaces this header's list of read group entries with those in + /// \p readGroups. + /// + /// \returns reference to this object + /// + BamHeader& ReadGroups(std::vector readGroups); + + /// \} + +public: + /// \name Sequences + /// \{ + + /// \brief Appends a sequence entry (\@SQ) to this header. + /// + /// \returns reference to this object + /// + BamHeader& AddSequence(SequenceInfo sequence); + + /// \brief Removes all sequence entries from this header. + /// + /// \returns reference to this object + /// + BamHeader& ClearSequences(); + + /// \brief Replaces this header's list of sequence entries with those in + /// \p sequences. + /// + /// \returns reference to this object + /// + BamHeader& Sequences(std::vector sequences); + + /// \} + +public: + /// \name Programs + /// \{ + + /// \brief Appends a program entry (\@PG) to this header. + /// + /// \returns reference to this object + /// + BamHeader& AddProgram(ProgramInfo pg); + + /// \brief Removes all program entries from this header. + /// + /// \returns reference to this object + /// + BamHeader& ClearPrograms(); + + /// \brief Replaces this header's list of program entries with those in + /// \p programs. + /// + /// \returns reference to this object + /// + BamHeader& Programs(std::vector programs); + + /// \} + +public: + /// \name Comments + /// \{ + + /// \brief Appends a comment (\@CO) to this header. + /// + /// \returns reference to this object + /// + BamHeader& AddComment(std::string comment); + + /// \brief Removes all comments from this header. + /// + /// \returns reference to this object + /// + BamHeader& ClearComments(); + + /// \brief Replaces this header's list of comments with those in \p comments. + /// + /// \returns reference to this object + /// + BamHeader& Comments(std::vector comments); + + /// \} + +private: + class BamHeaderPrivate; + std::shared_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMHEADER_H diff --git a/include/pbbam/BamReader.h b/include/pbbam/BamReader.h new file mode 100644 index 0000000..5afc696 --- /dev/null +++ b/include/pbbam/BamReader.h @@ -0,0 +1,152 @@ +// File Description +/// \file BamReader.h +/// \brief Defines the BamReader class. +// +// Author: Derek Barnett + +#ifndef BAMREADER_H +#define BAMREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +#include "pbbam/BamFile.h" +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/GenomicInterval.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The BamReader class provides basic read-access to a %BAM file. +/// +/// The base-class implementation provides a sequential read-through of BAM +/// records. Derived classes may implement other access schemes (e.g. genomic +/// region, PBI-enabled record filtering). +/// +class PBBAM_EXPORT BamReader : public internal::IQuery +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Opens BAM for streaming from stdin + BamReader(); + + /// \brief Opens BAM file for reading. + /// + /// \param[in] fn %BAM filename + /// \throws std::runtime_error if failed to open + /// + explicit BamReader(std::string fn); + + /// \brief Opens BAM file for reading. + /// + /// \param[in] bamFile BamFile object + /// \throws std::runtime_error if failed to open + /// + explicit BamReader(BamFile bamFile); + + virtual ~BamReader(); + + /// \} + +public: + /// \name BAM File Attributes + /// \{ + + /// \returns %BAM filename + const std::string& Filename() const; + + /// \returns BamHeader object from %BAM header contents + const BamHeader& Header() const; + + /// \} + +public: + /// \name BAM File I/O + /// \{ + + /// \brief Fetches the "next" %BAM record. + /// + /// Default implementation will read records until EOF. Derived readers may + /// use additional criteria to decide which record is "next" and when + /// reading is done. + /// + /// \param[out] record next BamRecord object. Should not be used if method + /// returns false. + /// + /// \returns true if record was read successfully. Returns false if EOF (or + /// end of iterator in derived readers). False is not an error, + /// it indicates "end of data". + /// + /// \throws std::runtime_error if failed to read from file (e.g. possible + /// truncated or corrupted file). + /// + bool GetNext(BamRecord& record); + + /// \brief Seeks to virtual offset in %BAM. + /// + /// \note This is \b NOT a normal file offset, but the virtual offset used + /// in %BAM indexing. + /// + /// \throws std::runtime_error if failed to seek + /// + void VirtualSeek(int64_t virtualOffset); + + /// \returns current (virtual) file position. + /// + /// \note This is \b NOT a normal file offset, but the virtual offset used + /// in %BAM indexing. + /// + int64_t VirtualTell() const; + + /// \} + +protected: + /// \name BAM File I/O + /// \{ + + /// \brief Helper method for access to underlying BGZF stream pointer. + /// + /// Useful for derived readers' contact points with htslib methods. + /// + /// \returns BGZF stream pointer + /// + BGZF* Bgzf() const; + + /// \brief Performs the actual raw read of the next record from the BAM + /// file. + /// + /// Default implementation will read records, sequentially, until EOF. + /// Derived readers may use additional criteria to decide which record is + /// "next" and when reading is done. + /// + /// Return value should be equivalent to htslib's bam_read1(): + /// >= 0 : normal + /// -1 : EOF (not an error) + /// < -1 : error + /// + /// \param[in] bgzf BGZF stream pointer + /// \param[out] b %BAM record pointer + /// \returns integer status code, see description + /// + virtual int ReadRawData(BGZF* bgzf, bam1_t* b); + + /// \} + +private: + class BamReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMREADER_H diff --git a/include/pbbam/BamRecord.h b/include/pbbam/BamRecord.h new file mode 100644 index 0000000..c0dc6be --- /dev/null +++ b/include/pbbam/BamRecord.h @@ -0,0 +1,1314 @@ +// File Description +/// \file BamRecord.h +/// \brief Defines the BamRecord class. +// +// Author: Derek Barnett + +#ifndef BAMRECORD_H +#define BAMRECORD_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pbbam/Accuracy.h" +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecordImpl.h" +#include "pbbam/ClipType.h" +#include "pbbam/FrameEncodingType.h" +#include "pbbam/Frames.h" +#include "pbbam/LocalContextFlags.h" +#include "pbbam/Orientation.h" +#include "pbbam/PulseBehavior.h" +#include "pbbam/PulseExclusionReason.h" +#include "pbbam/QualityValues.h" +#include "pbbam/ReadGroupInfo.h" +#include "pbbam/RecordType.h" +#include "pbbam/Strand.h" +#include "pbbam/ZmwType.h" +#include "pbbam/virtual/VirtualRegionType.h" + +namespace PacBio { +namespace BAM { + +class Pulse2BaseCache; + +/// \brief The BamRecord class represents a %PacBio %BAM record. +/// +/// %PacBio %BAM records are extensions of normal SAM/BAM records. Thus in +/// addition to normal fields like bases, qualities, mapping coordinates, etc., +/// tags are used extensively to annotate records with additional +/// PacBio-specific data. +/// +/// Mapping and clipping APIs are provided as well to ensure that such +/// operations "trickle down" to all data fields properly. +/// +/// \sa https://samtools.github.io/hts-specs/SAMv1.pdf +/// for more information on standard %BAM data, and +/// https://github.com/PacificBiosciences/PacBioFileFormats/blob/3.0/BAM.rst +/// for more information on %PacBio %BAM fields. +/// +class PBBAM_EXPORT BamRecord +{ +public: + /// \name Constructors & Related Methods + /// \{ + + BamRecord(); + BamRecord(BamHeader header); + BamRecord(BamRecordImpl impl); + BamRecord(const BamRecord& other); + BamRecord(BamRecord&& other) noexcept; + BamRecord& operator=(const BamRecord& other); + BamRecord& operator=(BamRecord&& other) noexcept; + virtual ~BamRecord(); + + /// \} + +public: + /// \name General Data + /// \{ + + /// \returns this record's full name + /// \sa BamRecordImpl::Name + /// + std::string FullName() const; + + /// \returns shared pointer to this record's associated BamHeader + BamHeader Header() const; + + /// \returns ZMW hole number + /// \throws if missing zm tag & record name does not contain hole number + /// + int32_t HoleNumber() const; + + /// \returns this record's LocalContextFlags + PacBio::BAM::LocalContextFlags LocalContextFlags() const; + + /// \returns this record's movie name + std::string MovieName() const; + + /// \returns "number of complete passes of the insert" + int32_t NumPasses() const; + + /// \returns the record's query end position, or Sequence().length() if not + /// stored + /// \note QueryEnd is in polymerase read coordinates, NOT genomic + /// coordinates. + /// + Position QueryEnd() const; + + /// \returns the number of frames from start of movie to the last base of read + /// + int32_t QueryEndFrameNumber() const; + + /// \returns the record's query start position, or 0 if not stored + /// + /// \note QueryStart is in polymerase read coordinates, NOT genomic + /// coordinates. + /// + Position QueryStart() const; + + /// \returns the number of frames from start of movie to the first base of read + /// + int32_t QueryStartFrameNumber() const; + + /// \returns this record's expected read accuracy [0, 1000] + Accuracy ReadAccuracy() const; + + /// \returns ReadGroupInfo object for this record + ReadGroupInfo ReadGroup() const; + + /// \returns string ID of this record's read group + /// + /// This method should be perferred over ReadGroupBaseId() in most cases, + /// e.g. mapping between header info. + /// + /// For "ID:12345678": + /// b.ReadGroupId() -> "12345678" + /// b.ReadGroupBaseId() -> "12345678" + /// + /// For "ID:12345678/0--0": + /// b.ReadGroupId() -> "12345678/0--0"; + /// b.ReadGroupBaseId -> "12345678" + /// + /// \sa BamRecord::ReadGroupBaseId + /// \sa ReadGroupInfo::Id + /// \sa ReadGroupInfo::BaseId + /// + std::string ReadGroupId() const; + + /// \returns string base ID (stripped of optional barcode labels) + /// + /// ReadGroupId() should be preferred over this method in most cases. This + /// is intended for use with hash-string or integers directly. + /// + /// For "ID:12345678": + /// b.ReadGroupId() -> "12345678" + /// b.ReadGroupBaseId() -> "12345678" + /// + /// For "ID:12345678/0--0": + /// b.ReadGroupId() -> "12345678/0--0"; + /// b.ReadGroupBaseId -> "12345678" + /// + /// \sa BamRecord::ReadGroupId + /// \sa ReadGroupInfo::Id + /// \sa ReadGroupInfo::BaseId + /// + std::string ReadGroupBaseId() const; + + /// \returns integer value for this record's read group ID + int32_t ReadGroupNumericId() const; + + /// \returns this scrap record's scrap region type + VirtualRegionType ScrapRegionType() const; + + /// \returns this scrap record's scrap ZMW type + ZmwType ScrapZmwType() const; + + /// \returns this record's average signal-to-noise for each of A, C, G, + /// and T + /// + std::vector SignalToNoise() const; + + /// \returns this record's type + /// \sa RecordType + RecordType Type() const; + + /// \} + +public: + /// \name Mapping Data + /// \{ + + /// \returns the record's aligned end position + /// + /// \note AlignedEnd is in polymerase read coordinates, NOT genomic + /// coordinates. + /// + Position AlignedEnd() const; + + /// \returns the record's aligned start position + /// + /// \note AlignedStart is in polymerase read coordinates, NOT genomic + /// coordinates. + /// + Position AlignedStart() const; + + /// \returns the record's strand as a Strand enum value + Strand AlignedStrand() const; + + /// \returns the record's CIGAR data as a Cigar object + /// + /// \param[in] exciseAllClips if true, remove all clipping operations + /// (hard & soft) [default:false] + /// + Cigar CigarData(bool exciseAllClips = false) const; + + /// \returns true if this record was mapped by aligner + bool IsMapped() const; + + /// \returns this record's mapping quality. A value of 255 indicates + /// "unknown" + /// + uint8_t MapQuality() const; + + /// \returns the number of deleted bases (relative to reference) + size_t NumDeletedBases() const; + + /// \returns the number of inserted bases (relative to reference) + size_t NumInsertedBases() const; + + /// \returns the number of matching bases (sum of '=' CIGAR op lengths) + size_t NumMatches() const; + + /// \returns a tuple containing NumMatches (first) and NumMismatches + /// (second) + /// + std::pair NumMatchesAndMismatches() const; + + /// \returns the number of mismatching bases (sum of 'X' CIGAR op lengths) + size_t NumMismatches() const; + + /// \returns this record's reference ID, or -1 if unmapped. + /// + /// \note This is only a valid identifier within this %BAM file + /// + int32_t ReferenceId() const; + + /// \returns this record's reference name. + /// + /// \throws an exception if unmapped record. + /// + std::string ReferenceName() const; + + /// \returns the record's reference end position, or UnmappedPosition if + /// unmapped + /// + /// \note ReferenceEnd is in reference coordinates, NOT polymerase read + /// coordinates. + /// + Position ReferenceEnd() const; + + /// \returns the record's reference start position, or UnmappedPosition if + /// unmapped + /// + /// \note ReferenceStart is in reference coordinates, NOT polymerase read + /// coordinates. + /// + Position ReferenceStart() const; + + /// \} + +public: + /// \name Barcode Data + /// \{ + + /// \returns forward barcode id + /// + /// \throws std::runtime_error if barcode data is absent or malformed. + /// \sa HasBarcodes + /// + int16_t BarcodeForward() const; + + /// \returns barcode call confidence (Phred-scaled posterior probability + /// of correct barcode call) + /// + /// \sa HasBarcodeQuality + /// + uint8_t BarcodeQuality() const; + + /// \returns reverse barcode id + /// + /// \throws std::runtime_error if barcode data is absent or malformed. + /// \sa HasBarcodes + /// + int16_t BarcodeReverse() const; + + /// \returns the forward and reverse barcode ids + /// + /// \throws std::runtime_error if barcode data is absent or malformed. + /// \sa HasBarcodes + /// + std::pair Barcodes() const; + + /// \} + +public: + /// \name Auxiliary Data Queries + /// \{ + + /// \returns true if this record has AltLabelQV data + bool HasAltLabelQV() const; + + /// \returns true if this record has AltLabelTag data + bool HasAltLabelTag() const; + + /// \returns true if this record has Barcode data + bool HasBarcodes() const; + + /// \returns true is this record has BarcodeQuality data + bool HasBarcodeQuality() const; + + /// \returns true if this record has DeletionQV data + bool HasDeletionQV() const; + + /// \returns true if this record has DeletionTag data + bool HasDeletionTag() const; + + /// \returns true if this record has a HoleNumber + bool HasHoleNumber() const; + + /// \returns true if this record has InsertionQV data + bool HasInsertionQV() const; + + /// \returns true if this record has IPD data + bool HasIPD() const; + + /// \returns true if this record has LabelQV data + bool HasLabelQV() const; + + /// \returns true if this record has LocalContextFlags (absent in CCS) + bool HasLocalContextFlags() const; + + /// \returns true if this record has MergeQV data + bool HasMergeQV() const; + + /// \returns true if this record has NumPasses data + bool HasNumPasses() const; + + /// \returns true if this record has Pkmean data + bool HasPkmean() const; + + /// \returns true if this record has Pkmid data + bool HasPkmid() const; + + /// \returns true if this record has Pkmean2 data + bool HasPkmean2() const; + + /// \returns true if this record has Pkmid2 data + bool HasPkmid2() const; + + /// \returns true if this record has PreBaseFrames aka IPD data + bool HasPreBaseFrames() const; + + /// \returns true if this record has PrePulseFrames data + bool HasPrePulseFrames() const; + + /// \returns true if this record has PulseCall data + bool HasPulseCall() const; + + /// \returns true if this record has PulseCallWidth data + bool HasPulseCallWidth() const; + + /// \returns true if this record has PulseExclusion data + bool HasPulseExclusion() const; + + /// \returns true if this record has PulseMergeQV data + bool HasPulseMergeQV() const; + + /// \returns true if this record has PulseWidth data + bool HasPulseWidth() const; + + /// \returns true if this record has ReadAccuracyTag data + bool HasReadAccuracy() const; + + /// \returns true if this record has QueryEnd data + bool HasQueryEnd() const; + + /// \returns true if this record has QueryEnd data + bool HasQueryEndFrameNumber() const; + + /// \returns true if this record has QueryStart data + bool HasQueryStart() const; + + /// \returns true if this record has QueryStartFrameNumber data + bool HasQueryStartFrameNumber() const; + + /// \returns true if this record has ScrapRegionType data (only in SCRAP) + bool HasScrapRegionType() const; + + /// \returns true if this record has scrap ZMW type data (only in SCRAP) + bool HasScrapZmwType() const; + + /// \returns true if this record has signal-to-noise data (absent in + /// POLYMERASE) + /// + bool HasSignalToNoise() const; + + /// \returns true if this record has StartFrame data + bool HasStartFrame() const; + + /// \returns true if this record has SubstitutionQV data + bool HasSubstitutionQV() const; + + /// \returns true if this record has SubstitutionTag data + bool HasSubstitutionTag() const; + + /// \} + +public: + /// \name Sequence & Tag Data + /// \{ + + /// \brief Fetches this record's AltLabelTag values ("pt" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new gap chars will be '-' and padding chars will be '*'. + /// + /// \param[in] orientation Orientation of output. + /// + /// \returns AltLabelTags string + /// + std::string AltLabelTag(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's DeletionTag values ("dt" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new gap chars will be '-' and padding chars will be '*'. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns DeletionTag string + /// + std::string DeletionTag(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's DNA sequence (SEQ field). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new gap chars will be '-' and padding chars will be '*'. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns sequence string + /// + std::string Sequence(const Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's SubstitutionTag values ("st" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new gap chars will be '-' and padding chars will be '*'. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns SubstitutionTags string + /// + std::string SubstitutionTag(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \} + +public: + /// \name Quality Data + /// \{ + + /// \brief Fetches this record's AltLabelQV values ("pv" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new QVs will have a value of 0. + /// + /// \param[in] orientation Orientation of output. + /// + /// \returns AltLabelQV as QualityValues object + /// + QualityValues AltLabelQV(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's DeletionQV values ("dq" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new QVs will have a value of 0. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns DeletionQV as QualityValues object + /// + QualityValues DeletionQV(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's InsertionQV values ("iq" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new QVs will have a value of 0. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns InsertionQVs as QualityValues object + /// + QualityValues InsertionQV(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's LabelQV values ("pq" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new QVs will have a value of 0. + /// + /// \param[in] orientation Orientation of output. + /// + /// \returns LabelQV as QualityValues object + /// + QualityValues LabelQV(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's MergeQV values ("mq" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new QVs will have a value of 0. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns MergeQV as QualityValues object + /// + QualityValues MergeQV(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's %BAM quality values (QUAL field). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new QVs will have a value of 0. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns %BAM qualities as QualityValues object + /// + QualityValues Qualities(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's SubstitutionQV values ("sq" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new QVs will have a value of 0. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns SubstitutionQV as QualityValues object + /// + QualityValues SubstitutionQV(Orientation orientation = Orientation::NATIVE, + bool aligned = false, bool exciseSoftClips = false) const; + + /// \} + +public: + /// \name Pulse Data + /// \{ + + /// \brief Fetches this record's IPD values ("ip" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new frames will have a value of 0; + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns IPD as Frames object + /// + Frames IPD(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's IPD values ("ip" tag), but does not upscale. + /// + /// \param[in] orientation Orientation of output. + /// \returns IPD as Frames object + /// + Frames IPDRaw(Orientation orientation = Orientation::NATIVE) const; + + /// \brief Fetches this record's Pkmean values ("pa" tag). + /// + /// \param[in] orientation Orientation of output. + /// \returns Pkmean as vector object + /// + std::vector Pkmean(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's Pkmid values ("pm" tag). + /// + /// \param[in] orientation Orientation of output. + /// \returns Pkmid as vector object + /// + std::vector Pkmid(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's Pkmean2 values ("pi" tag). + /// + /// \param[in] orientation Orientation of output. + /// \returns Pkmean as vector object + /// + std::vector Pkmean2(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's Pkmid2 values ("ps" tag). + /// + /// \param[in] orientation Orientation of output. + /// \returns Pkmid as vector object + /// + std::vector Pkmid2(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's PreBaseFrames aka IPD values ("ip" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new frames will have a value of 0; + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns IPD as Frames object + /// + Frames PreBaseFrames(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's PrePulseFrames values ("pd" tag). + /// + /// \param[in] orientation Orientation of output. + /// \returns PrePulseFrames as Frames object + /// + Frames PrePulseFrames(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's PulseCall values ("pc" tag). + /// + /// \param[in] orientation Orientation of output. + /// \returns PulseCalls string + /// + std::string PulseCall(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's PulseCallWidth values ("px" tag). + /// + /// \param[in] orientation Orientation of output. + /// \returns PulseCallWidth as Frames object + /// + Frames PulseCallWidth(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's PulseExclusionReason values ("pe" tag). + /// + /// \returns vector of pulse exclusion reason value + /// + std::vector PulseExclusionReason( + Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetch this record's PulseMergeQV values ("pg" tag). + /// + /// \param[in] orientation Orientation of output. + /// \returns PulseMergeQV as QualityValues object + /// + QualityValues PulseMergeQV(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \brief Fetches this record's PulseWidth values ("pw" tag). + /// + /// \note If \p aligned is true, and gaps/padding need to be inserted, the + /// new frames will have a value of 0. + /// + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns PulseWidths as Frames object + /// + Frames PulseWidth(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's PulseWidth values ("pw" tag), but does not + /// upscale. + /// + /// \param[in] orientation Orientation of output. + /// \returns PulseWidth as Frames object + /// + Frames PulseWidthRaw(Orientation orientation = Orientation::NATIVE, bool aligned = false, + bool exciseSoftClips = false) const; + + /// \brief Fetches this record's StartFrame values ("sf" tag). + /// + /// \param[in] orientation Orientation of output + /// + /// \returns StartFrame as uint32_t vector + /// + std::vector StartFrame(Orientation orientation = Orientation::NATIVE, + bool aligned = false, bool exciseSoftClips = false, + PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + /// \} + +public: + /// \name Low-Level Access & Operations + /// \{ + + /// \warning This method should be considered temporary and avoided as much + /// as possible. Direct access to the internal object is likely to + /// disappear as BamRecord interface matures. + /// + /// \returns const reference to underlying BamRecordImpl object + /// + const BamRecordImpl& Impl() const; + + /// \warning This method should be considered temporary and avoided as much + /// as possible. Direct access to the internal object is likely to + /// disappear as BamRecord interface matures. + /// + /// \returns reference to underlying BamRecordImpl object + /// + BamRecordImpl& Impl(); + + /// \} + +public: + /// \name General Data + /// \{ + + /// \brief Sets this record's ZMW hole number. + /// + /// \param[in] holeNumber + /// \returns reference to this record + /// + BamRecord& HoleNumber(const int32_t holeNumber); + + /// \brief Sets this record's local context flags + /// + /// \param[in] flags + /// \returns reference to this record + /// + BamRecord& LocalContextFlags(const PacBio::BAM::LocalContextFlags flags); + + /// \brief Sets this record's "number of complete passes of the insert". + /// + /// \param[in] numPasses + /// \returns reference to this record + /// + BamRecord& NumPasses(const int32_t numPasses); + + /// \brief Sets this record's query end position. + /// + /// \note Changing this will modify the name of non-CCS records. + /// + /// \param[in] pos + /// \returns reference to this record + /// + BamRecord& QueryEnd(const PacBio::BAM::Position pos); + + /// \brief Sets this record's query end frame number + /// + /// \param[in] frame number + /// \returns reference to this record + /// + BamRecord& QueryEndFrameNumber(const int32_t frameNumber); + + /// \brief Sets this record's query start position. + /// + /// \note Changing this will modify the name of non-CCS records. + /// + /// \param[in] pos + /// \returns reference to this record + /// + BamRecord& QueryStart(const PacBio::BAM::Position pos); + + /// \brief Sets this record's query start frame number + /// + /// \param[in] frame number + /// \returns reference to this record + /// + BamRecord& QueryStartFrameNumber(const int32_t frameNumber); + + /// \brief Sets this record's expected read accuracy [0, 1000] + /// + /// \param[in] accuracy + /// \returns reference to this record + /// + BamRecord& ReadAccuracy(const Accuracy& accuracy); + + /// \brief Attaches this record to the provided read group, changing the + /// record name & 'RG' tag. + /// + /// \param[in] rg + /// \returns reference to this record + /// + BamRecord& ReadGroup(const ReadGroupInfo& rg); + + /// \brief Attaches this record to the provided read group, changing the + /// record name & 'RG' tag. + /// + /// \param[in] id + /// \returns reference to this record + /// + BamRecord& ReadGroupId(const std::string& id); + + /// \brief Sets this scrap record's ScrapRegionType + /// + /// \param[in] type + /// \returns reference to this record + /// + BamRecord& ScrapRegionType(const VirtualRegionType type); + + /// \brief Sets this scrap record's ScrapRegionType + /// + /// \param[in] type character equivalent of VirtualRegionType + /// \returns reference to this record + /// + BamRecord& ScrapRegionType(const char type); + + /// \brief Sets this scrap record's ScrapZmwType + /// + /// \param[in] type + /// \returns reference to this record + /// + BamRecord& ScrapZmwType(const ZmwType type); + + /// \brief Sets this scrap record's ScrapZmwType + /// + /// \param[in] type character equivalent of ZmwType + /// \returns reference to this record + /// + BamRecord& ScrapZmwType(const char type); + + /// \brief Sets this record's average signal-to-noise in each of A, C, G, + /// and T + /// + /// \param[in] snr average signal-to-noise of A, C, G, and T (in this order) + /// \returns reference to this record + /// + BamRecord& SignalToNoise(const std::vector& snr); + + /// \} + +public: + /// \name Barcode Data + /// \{ + + /// \brief Sets this record's barcode IDs ('bc' tag) + /// + /// \param[in] barcodeIds + /// \returns reference to this record + /// + BamRecord& Barcodes(const std::pair& barcodeIds); + + /// \brief Sets this record's barcode quality ('bq' tag) + /// + /// \param[in] quality Phred-scaled confidence call + /// \returns reference to this record + /// + BamRecord& BarcodeQuality(const uint8_t quality); + + /// \} + +public: + /// \name Sequence & Tag Data + /// \{ + + /// \brief Sets this record's AltLabelTag values ("at" tag). + /// + /// \param[in] tags + /// \returns reference to this record + /// + BamRecord& AltLabelTag(const std::string& tags); + + /// \brief Sets this record's DeletionTag values ("dt" tag). + /// + /// \param[in] tags + /// \returns reference to this record + /// + BamRecord& DeletionTag(const std::string& tags); + + /// \brief Sets this record's SubstitutionTag values ("st" tag). + /// + /// \param[in] tags + /// \returns reference to this record + /// + BamRecord& SubstitutionTag(const std::string& tags); + + /// \} + +public: + /// \name Quality Data + /// \{ + + /// \brief Sets this record's AltLabelQV values ("pv" tag). + /// + /// \param[in] altLabelQVs + /// \returns reference to this record + /// + BamRecord& AltLabelQV(const QualityValues& altLabelQVs); + + /// \brief Sets this record's DeletionQV values ("dq" tag). + /// + /// \param[in] deletionQVs + /// \returns reference to this record + /// + BamRecord& DeletionQV(const QualityValues& deletionQVs); + + /// \brief Sets this record's InsertionQV values ("iq" tag). + /// + /// \param[in] insertionQVs + /// \returns reference to this record + /// + BamRecord& InsertionQV(const QualityValues& insertionQVs); + + /// \brief Sets this record's LabelQV values ("pq" tag). + /// + /// \param[in] labelQVs + /// \returns reference to this record + /// + BamRecord& LabelQV(const QualityValues& labelQVs); + + /// \brief Sets this record's MergeQV values ("mq" tag). + /// + /// \param[in] mergeQVs + /// \returns reference to this record + /// + BamRecord& MergeQV(const QualityValues& mergeQVs); + + /// \brief Sets this record's SubstitutionQV values ("sq" tag). + /// + /// \param[in] substitutionQVs + /// \returns reference to this record + /// + BamRecord& SubstitutionQV(const QualityValues& substitutionQVs); + + /// \} + +public: + /// \name Pulse Data + /// \{ + + /// \brief Sets this record's IPD values ("ip" tag). + /// + /// \param[in] frames + /// \param[in] encoding specify how to encode the data (8-bit lossy, or + /// 16-bit lossless) + /// \returns reference to this record + /// + BamRecord& IPD(const Frames& frames, const FrameEncodingType encoding); + + /// \brief Sets this record's Pkmean values ("pm" tag). + /// + /// \param[in] photons + /// \returns reference to this record + /// + BamRecord& Pkmean(const std::vector& photons); + + /// \brief Sets this record's Pkmean values ("pm" tag). + /// + /// \param[in] encodedPhotons + /// \returns reference to this record + /// + BamRecord& Pkmean(const std::vector& encodedPhotons); + + /// \brief Sets this record's Pkmid values ("pa" tag). + /// + /// \param[in] photons + /// \returns reference to this record + /// + BamRecord& Pkmid(const std::vector& photons); + + /// \brief Sets this record's Pkmid values ("pa" tag). + /// + /// \param[in] encodedPhotons + /// \returns reference to this record + /// + BamRecord& Pkmid(const std::vector& encodedPhotons); + + /// \brief Sets this record's Pkmean2 values ("ps" tag). + /// + /// \param[in] photons + /// \returns reference to this record + /// + BamRecord& Pkmean2(const std::vector& photons); + + /// \brief Sets this record's Pkmean2 values ("ps" tag). + /// + /// \param[in] encodedPhotons + /// \returns reference to this record + /// + BamRecord& Pkmean2(const std::vector& encodedPhotons); + + /// \brief Sets this record's Pkmid2 values ("pi" tag). + /// + /// \param[in] photons + /// \returns reference to this record + /// + BamRecord& Pkmid2(const std::vector& photons); + + /// \brief Sets this record's Pkmid2 values ("pi" tag). + /// + /// \param[in] encodedPhotons + /// \returns reference to this record + /// + BamRecord& Pkmid2(const std::vector& encodedPhotons); + + /// \brief Sets this record's PreBaseFrames aka IPD values ("ip" tag). + /// + /// \param[in] frames + /// \param[in] encoding specify how to encode the data (8-bit lossy, or + /// 16-bit lossless) + /// \returns reference to this record + /// + BamRecord& PreBaseFrames(const Frames& frames, const FrameEncodingType encoding); + + /// \brief Sets this record's PrePulseFrames values ("pd" tag). + /// + /// \param[in] frames + /// \param[in] encoding specify how to encode the data (8-bit lossy, or + /// 16-bit lossless) + /// \returns reference to this record + /// + BamRecord& PrePulseFrames(const Frames& frames, const FrameEncodingType encoding); + + /// \brief Sets this record's PulseCall values ("pc" tag). + /// + /// \param[in] tags + /// \returns reference to this record + /// + BamRecord& PulseCall(const std::string& tags); + + /// \brief Sets this record's PulseCallWidth values ("px" tag). + /// + /// \param[in] frames + /// \param[in] encoding specify how to encode the data (8-bit lossy, or + /// 16-bit lossless) + /// \returns reference to this record + /// + BamRecord& PulseCallWidth(const Frames& frames, const FrameEncodingType encoding); + + /// + /// \\brief Sets this record's PulseExclusionReason values ("pe" tag). + /// \param[in] reasons + /// \return reference to this record + /// + BamRecord& PulseExclusionReason(const std::vector& reasons); + + /// \brief Sets this record's PulseMergeQV values ("pg" tag). + /// + /// \param[in] pulseMergeQVs + /// \returns reference to this record + /// + BamRecord& PulseMergeQV(const QualityValues& pulseMergeQVs); + + /// \brief Sets this record's PulseWidth values ("pw" tag). + /// + /// \param[in] frames + /// \param[in] encoding specify how to encode the data (8-bit lossy, or + /// 16-bit lossless) + /// \returns reference to this record + /// + BamRecord& PulseWidth(const Frames& frames, const FrameEncodingType encoding); + + /// \brief Sets this record's StartFrame values ("sf" tag). + /// + /// \param[in] startFrame + /// \returns reference to this record + /// + BamRecord& StartFrame(const std::vector& startFrame); + + /// \} + +public: + /// \name Low-Level Access & Operations + /// \{ + + /// \brief Resets cached aligned start/end. + /// + /// \note This method should not be needed in most client code. It exists + /// primarily as a hook for internal reading loops (queries, index + /// build, etc.) It's essentially a workaround and will likely be + /// removed from the API. + /// + void ResetCachedPositions() const; + + /// \brief Resets cached aligned start/end. + /// + /// \note This method should not be needed in most client code. It exists + /// primarily as a hook for internal reading loops (queries, index + /// build, etc.) It's essentially a workaround and will likely be + /// removed from the API. + /// + void ResetCachedPositions(); + + /// \brief Updates the record's name (BamRecord::FullName) to reflect + /// modifications to name components (movie name, ZMW hole number, + /// etc.) + /// + void UpdateName(); + + /// \} + +public: + /// \name Pulse Data + /// \{ + + static const float photonFactor; + + static std::vector EncodePhotons(const std::vector& data); + + /// \} + +public: + /// \name [Mapped]Read conversion + /// \{ + + /// + /// \return Data::Read representation of this record + /// + Data::Read ToRead() const; + + /// + /// \return Data::MappedRead representation of this record + /// + /// \throws std::runtime_error if record is unmapped + /// + Data::MappedRead ToMappedRead() const; + + /// \} + +public: + /// \name Clipping & Mapping + /// \{ + + /// Creates a copied record from input, with clipping applied + static BamRecord Clipped(const BamRecord& input, const ClipType clipType, + const PacBio::BAM::Position start, const PacBio::BAM::Position end, + const bool exciseFlankingInserts = false); + + /// Creates a copied record from input, with mapping applied + static BamRecord Mapped(const BamRecord& input, const int32_t referenceId, + const Position refStart, const Strand strand, const Cigar& cigar, + const uint8_t mappingQuality); + + /// Applies clipping to this record + BamRecord& Clip(const ClipType clipType, const PacBio::BAM::Position start, + const PacBio::BAM::Position end, const bool exciseFlankingInserts = false); + + /// Creates a copied record from this one, with clipping applied + BamRecord Clipped(const ClipType clipType, const PacBio::BAM::Position start, + const PacBio::BAM::Position end, + const bool exciseFlankingInserts = false) const; + + /// Applies mapping to this record + BamRecord& Map(const int32_t referenceId, const Position refStart, const Strand strand, + const Cigar& cigar, const uint8_t mappingQuality); + + /// Creates a copied record from this one, with mapping applied + BamRecord Mapped(const int32_t referenceId, const Position refStart, const Strand strand, + const Cigar& cigar, const uint8_t mappingQuality) const; + /// \} + +private: + BamRecordImpl impl_; + +public: + /// public & mutable so that queries can directly set the header info, + /// even on a record that is const from client code's perspective + mutable BamHeader header_; + +private: + /// \internal + /// cached positions (mutable to allow lazy-calc in const methods) + mutable Position alignedStart_; + mutable Position alignedEnd_; + +private: + /// \internal + /// pulse to bam mapping cache + mutable std::unique_ptr p2bCache_; + +public: + /// clips the PacBio tags to a specified length + void ClipTags(const size_t clipPos, const size_t clipLength); + +private: + ///\internal + /// clipping methods + + void ClipFields(const size_t clipPos, const size_t clipLength); + + BamRecord& ClipToQuery(const PacBio::BAM::Position start, const PacBio::BAM::Position end); + BamRecord& ClipToReference(const PacBio::BAM::Position start, const PacBio::BAM::Position end, + const bool exciseFlankingInserts); + +private: + ///\internal + /// raw tag data fetching + + // sequence tags + std::string FetchBasesRaw(const BamRecordTag tag) const; + std::string FetchBases(const BamRecordTag tag, + const Orientation orientation = Orientation::NATIVE, + const bool aligned = false, const bool exciseSoftClips = false, + const PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + // frame tags + Frames FetchFramesRaw(const BamRecordTag tag) const; + Frames FetchFrames(const BamRecordTag tag, const Orientation orientation = Orientation::NATIVE, + const bool aligned = false, const bool exciseSoftClips = false, + const PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + // pulse tags + std::vector FetchPhotonsRaw(const BamRecordTag tag) const; + std::vector FetchPhotons(const BamRecordTag tag, + const Orientation orientation = Orientation::NATIVE, + const bool aligned = false, const bool exciseSoftClips = false, + const PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + // QV tags + QualityValues FetchQualitiesRaw(const BamRecordTag tag) const; + QualityValues FetchQualities(const BamRecordTag tag, + const Orientation orientation = Orientation::NATIVE, + const bool aligned = false, const bool exciseSoftClips = false, + const PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + // UInt tags (e.g. start frame) + // + // TODO (DB): clean this up w.r.t FetchUInt8s + // + std::vector FetchUInt32sRaw(const BamRecordTag tag) const; + std::vector FetchUInt32s( + const BamRecordTag tag, const Orientation orientation = Orientation::NATIVE, + const bool aligned = false, const bool exciseSoftClips = false, + const PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + + // UInt tags (e.g. pulse exclusion) + // + // ODO (DB): clean this up w.r.t FetchUInt32s + // + std::vector FetchUInt8sRaw(const BamRecordTag tag) const; + std::vector FetchUInt8s(const BamRecordTag tag, + const Orientation orientation = Orientation::NATIVE, + const bool aligned = false, const bool exciseSoftClips = false, + const PulseBehavior pulseBehavior = PulseBehavior::ALL) const; + +private: + ///\internal + /// marked const to allow calling from const methods + /// but updates our mutable cached values + void CalculateAlignedPositions() const; + void CalculatePulse2BaseCache() const; + + friend class BamRecordMemory; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMRECORD_H diff --git a/include/pbbam/BamRecordBuilder.h b/include/pbbam/BamRecordBuilder.h new file mode 100644 index 0000000..b1c1080 --- /dev/null +++ b/include/pbbam/BamRecordBuilder.h @@ -0,0 +1,239 @@ +// File Description +/// \file BamRecordBuilder.h +/// \brief Defines the BamRecordBuilder class. +// +// Author: Derek Barnett + +#ifndef BAMRECORDBUILDER_H +#define BAMRECORDBUILDER_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecord.h" + +namespace PacBio { +namespace BAM { + +/// \brief The BamRecordBuilder class provides a helper utility for building +/// BamRecords. +/// +/// This class provides a mechanism for building up %BAM data and +/// lazy-encoding/constructing the actual BamRecord. Currently, the methods here +/// really only support filling in the low-level SAM/BAM-style fields, not so +/// much the PacBio-specific fields. +/// +class PBBAM_EXPORT BamRecordBuilder +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates an empty %BAM record builder. + BamRecordBuilder(); + + /// \brief Creates an empty %BAM record builder, with header info to apply + /// to built records. + /// + /// \param[in] header BamHeader object + /// + explicit BamRecordBuilder(BamHeader header); + + /// \brief Creates record builder with inital record data. + /// + /// \param[in] prototype data from this record will be used to seed the + /// builder + /// + BamRecordBuilder(const BamRecord& prototype); + + /// \} + +public: + /// \name Record-Building + /// \{ + + /// \brief Builds a BamRecord from current builder attributes. + /// + /// \returns newly-built BamRecord object + /// + BamRecord Build() const; + + /// \brief Replaces an existing BamRecord's data with current builder + /// attributes. + /// + /// \param[out] record resulting record + /// \returns true if successful + /// + bool BuildInPlace(BamRecord& record) const; + + /// \brief Resets builder attributes to default values. + /// + void Reset(); + + /// \brief Resets builder attributes with \p prototype's data. + /// + /// \param[in] prototype + /// + void Reset(BamRecord prototype); + + /// \} + +public: + /// \name Core Attribute Setup + /// \{ + + /// \brief Sets the record's (BAI) index bin ID. + /// + /// \param[in] bin BAI index bin ID. + /// \returns reference to this builder + /// + BamRecordBuilder& Bin(const uint32_t bin); + + /// \brief Sets this record's alignment flag, using a raw integer. + /// + /// \param[in] flag raw alignment flag + /// \returns reference to this record + /// + BamRecordBuilder& Flag(const uint32_t flag); + + /// \brief Sets this record's insert size. + /// + /// \param[in] iSize insert size + /// \returns reference to this record + /// + BamRecordBuilder& InsertSize(const int32_t iSize); + + /// \brief Sets this record's map quality. + /// + /// \param[in] mapQual mapping quality - value of 255 indicates "unknown" + /// \returns reference to this record + /// + BamRecordBuilder& MapQuality(const uint8_t mapQual); + + /// \brief Sets this record's mate's mapped position. + /// + /// \param[in] pos mapped position. A value of -1 indicates unmapped. + /// \returns reference to this record + /// + BamRecordBuilder& MatePosition(const int32_t pos); + + /// \brief Sets this record's mate's mapped reference ID + /// + /// \param[in] id reference ID. A value of -1 indicates unmapped. + /// \returns reference to this record + /// + BamRecordBuilder& MateReferenceId(const int32_t id); + + /// \brief Sets this record's mapped position. + /// + /// \param[in] pos mapped position. A value of -1 indicates unmapped. + /// \returns reference to this record + /// + BamRecordBuilder& Position(const int32_t pos); + + /// \brief Sets this record's mapped reference ID + /// + /// \param[in] id reference ID. A value of -1 indicates unmapped. + /// \returns reference to this record + /// + BamRecordBuilder& ReferenceId(const int32_t id); + + /// \} + +public: + /// \name Alignment Flag Setup + /// \{ + + /// \brief Sets whether this record is a PCR/optical duplicate + BamRecordBuilder& SetDuplicate(bool ok); + + /// \brief Sets whether this record failed quality controls + BamRecordBuilder& SetFailedQC(bool ok); + + /// \brief Sets whether this record is the first mate of a pair. + BamRecordBuilder& SetFirstMate(bool ok); + + /// \brief Sets whether this record was aligned. + BamRecordBuilder& SetMapped(bool ok); + + /// \brief Sets whether this record's mate was aligned. + BamRecordBuilder& SetMateMapped(bool ok); + + /// \brief Sets whether this record's mate mapped to reverse strand. + BamRecordBuilder& SetMateReverseStrand(bool ok); + + /// \brief Sets whether this record came from paired-end sequencing. + BamRecordBuilder& SetPaired(bool ok); + + /// \brief Sets whether this record is a read's primary alignment. + BamRecordBuilder& SetPrimaryAlignment(bool ok); + + /// \brief Sets whether this record & its mate were properly mapped, per the + /// aligner. + /// + BamRecordBuilder& SetProperPair(bool ok); + + /// \brief Sets whether this record mapped to reverse strand. + BamRecordBuilder& SetReverseStrand(bool ok); + + /// \brief Sets whether this record is the second mate of a pair. + BamRecordBuilder& SetSecondMate(bool ok); + + /// \brief Sets whether this record is a supplementary alignment. + BamRecordBuilder& SetSupplementaryAlignment(bool ok); + + /// \} + +public: + /// \name Variable-Length Data Setup + /// \{ + + /// \brief Sets the record's CIGAR data. + /// + /// \returns reference to this builder + /// + BamRecordBuilder& Cigar(PacBio::BAM::Cigar cigar); + + /// \brief Sets the record's name. + /// + /// \returns reference to this builder + /// + BamRecordBuilder& Name(std::string name); + + /// \brief Sets the record's qualities. + /// + /// \returns reference to this builder + /// + BamRecordBuilder& Qualities(std::string qualities); + + /// \brief Sets the record's sequence. + /// + /// \returns reference to this builder + /// + BamRecordBuilder& Sequence(std::string sequence); + + /// \brief Sets the record's tags. + /// + /// \returns reference to this builder + /// + BamRecordBuilder& Tags(TagCollection tags); + + /// \} + +private: + BamHeader header_; + bam1_core_t core_; + std::string name_; + std::string sequence_; + std::string qualities_; + PacBio::BAM::Cigar cigar_; + TagCollection tags_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMRECORDBUILDER_H diff --git a/include/pbbam/BamRecordImpl.h b/include/pbbam/BamRecordImpl.h new file mode 100644 index 0000000..81a8a03 --- /dev/null +++ b/include/pbbam/BamRecordImpl.h @@ -0,0 +1,594 @@ +// File Description +/// \file BamRecordImpl.h +/// \brief Defines the BamRecordImpl class. +// +// Author: Derek Barnett + +#ifndef BAMRECORDIMPL_H +#define BAMRECORDIMPL_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "pbbam/BamRecordTag.h" +#include "pbbam/Cigar.h" +#include "pbbam/Position.h" +#include "pbbam/QualityValues.h" +#include "pbbam/TagCollection.h" + +namespace PacBio { +namespace BAM { + +class SamWriter; + +/// \brief The BamRecordImpl class holds all data necessary for creating, +/// querying or editing a generic %BAM record. +/// +/// For PacBio-specific extensions and convenience methods, see BamRecord. +/// +/// \note This class is mostly an internal implementation detail and will +/// likely be removed from the public API in the future. Please use +/// BamRecord as much as possible. +/// +class PBBAM_EXPORT BamRecordImpl +{ +public: + // clang-format off + /// These flags describe the alignment status of the record. + enum AlignmentFlag + { + PAIRED = 0x0001, ///< Record comes from paired-end sequencing + PROPER_PAIR = 0x0002, ///< Each mate of a pair was properly aligned ("proper" as determined by aligner) + UNMAPPED = 0x0004, ///< Record was not mapped by aligner + MATE_UNMAPPED = 0x0008, ///< Record's mate was not mapped by aligner + REVERSE_STRAND = 0x0010, ///< Record was aligned to reverse strand (Sequence() is reverse-complemented) + MATE_REVERSE_STRAND = 0x0020, ///< Record's mate was aligned to reverse strand (mate's Sequence() is reverse-complemented) + MATE_1 = 0x0040, ///< Record is first mate of pair + MATE_2 = 0x0080, ///< Record is second mate of pair + SECONDARY = 0x0100, ///< Record is a secondary alignment + FAILED_QC = 0x0200, ///< Record failed quality controls + DUPLICATE = 0x0400, ///< Record is a PCR/optical duplicate + SUPPLEMENTARY = 0x0800 ///< Record is a supplementary alignment + }; + // clang-format on + +public: + /// \name Constructors & Related Methods + /// \{ + + BamRecordImpl(); + BamRecordImpl(const BamRecordImpl& other); + BamRecordImpl(BamRecordImpl&& other) noexcept = default; + BamRecordImpl& operator=(const BamRecordImpl& other); + BamRecordImpl& operator=(BamRecordImpl&& other) noexcept = default; + virtual ~BamRecordImpl() = default; + + /// \} + +public: + /// \name Core Data + /// \{ + + /// \returns this record's assigned (BAI) index bin ID. + uint32_t Bin() const; + + /// \returns this record's alignment flag, in raw integer form. + uint32_t Flag() const; + + /// \returns this record's insert size + int32_t InsertSize() const; + + /// \returns this record's mapping quality. A value of 255 indicates "unknown" + uint8_t MapQuality() const; + + /// \returns this record's mate's mapped position, or -1 if unmapped + PacBio::BAM::Position MatePosition() const; + + /// \returns this record's mate's mapped reference ID, or -1 if unmapped + int32_t MateReferenceId() const; + + /// \returns this record's mapped position, or -1 if unmapped + PacBio::BAM::Position Position() const; + + /// \returns this record's mate's mapped reference ID, or -1 if unmapped + int32_t ReferenceId() const; + + /// Sets the record's (BAI) index bin ID. + /// + /// \param[in] bin BAI index bin ID. + /// \returns reference to this record + /// + BamRecordImpl& Bin(uint32_t bin); + + /// Sets this record's alignment flag, using a raw integer. + /// + /// \param[in] flag raw alignment flag + /// \returns reference to this record + /// + BamRecordImpl& Flag(uint32_t flag); + + /// Sets this record's insert size. + /// + /// \param[in] iSize insert size + /// \returns reference to this record + /// + BamRecordImpl& InsertSize(int32_t iSize); + + /// Sets this record's map quality. + /// + /// \param[in] mapQual mapping quality - value of 255 indicates "unknown" + /// \returns reference to this record + /// + BamRecordImpl& MapQuality(uint8_t mapQual); + + /// Sets this record's mate's mapped position. + /// + /// \param[in] pos mapped position. A value of -1 indicates unmapped. + /// \returns reference to this record + /// + BamRecordImpl& MatePosition(PacBio::BAM::Position pos); + + /// Sets this record's mate's mapped reference ID + /// + /// \param[in] id reference ID. A value of -1 indicates unmapped. + /// \returns reference to this record + /// + BamRecordImpl& MateReferenceId(int32_t id); + + /// Sets this record's mapped position. + /// + /// \param[in] pos mapped position. A value of -1 indicates unmapped. + /// \returns reference to this record + /// + BamRecordImpl& Position(PacBio::BAM::Position pos); + + /// Sets this record's mapped reference ID + /// + /// \param[in] id reference ID. A value of -1 indicates unmapped. + /// \returns reference to this record + /// + BamRecordImpl& ReferenceId(int32_t id); + + /// \} + +public: + /// \name Alignment Flags + /// \{ + + /// \returns true if this record is a PCR/optical duplicate + bool IsDuplicate() const; + + /// \returns true if this record failed quality controls + bool IsFailedQC() const; + + /// \returns true if this record is the first mate of a pair + bool IsFirstMate() const; + + /// \returns true if this record was mapped by aligner + bool IsMapped() const; + + /// \returns true if this record's mate was mapped by aligner + bool IsMateMapped() const; + + /// \returns true if this record's mate was mapped to the reverse strand + bool IsMateReverseStrand() const; + + /// \returns true if this record comes from paired-end sequencing + bool IsPaired() const; + + /// \returns true if this record is a read's primary alignment + bool IsPrimaryAlignment() const; + + /// \returns true if this record & its mate were properly aligned + bool IsProperPair() const; + + /// \returns true if this record was mapped to the reverse strand + bool IsReverseStrand() const; + + /// \returns true if this record is the second mate of a pair + bool IsSecondMate() const; + + /// \returns true if this record is a supplementary alignment + bool IsSupplementaryAlignment() const; + + /// Sets whether this record is a PCR/optical duplicate + BamRecordImpl& SetDuplicate(bool ok); + + /// Sets whether this record failed quality controls + BamRecordImpl& SetFailedQC(bool ok); + + /// Sets whether this record is the first mate of a pair. + BamRecordImpl& SetFirstMate(bool ok); + + /// Sets whether this record was aligned. + BamRecordImpl& SetMapped(bool ok); + + /// Sets whether this record's mate was aligned. + BamRecordImpl& SetMateMapped(bool ok); + + /// Sets whether this record's mate mapped to reverse strand. + BamRecordImpl& SetMateReverseStrand(bool ok); + + /// Sets whether this record came from paired-end sequencing. + BamRecordImpl& SetPaired(bool ok); + + /// Sets whether this record is a read's primary alignment. + BamRecordImpl& SetPrimaryAlignment(bool ok); + + /// Sets whether this record & its mate were properly mapped, per the aligner. + BamRecordImpl& SetProperPair(bool ok); + + /// Sets whether this record mapped to reverse strand. + BamRecordImpl& SetReverseStrand(bool ok); + + /// Sets whether this record is the second mate of a pair. + BamRecordImpl& SetSecondMate(bool ok); + + /// Sets whether this record is a supplementary alignment. + BamRecordImpl& SetSupplementaryAlignment(bool ok); + + /// \} + +public: + /// \name Variable-length Data (sequence, qualities, etc.) + /// \{ + + /// \returns the record's CIGAR data as a Cigar object + Cigar CigarData() const; + + /// Sets the record's CIGAR data using a Cigar object + /// + /// \param[in] cigar PacBio::BAM::Cigar object + /// \returns reference to this record + /// + BamRecordImpl& CigarData(const Cigar& cigar); + + /// Sets the record's CIGAR data using a CIGAR-formatted string. + /// + /// \param[in] cigarString CIGAR-formatted string + /// \returns reference to this record + /// + BamRecordImpl& CigarData(const std::string& cigarString); + + // TODO: CIGAR iterator - Cigar only or here as well ?? + + /// \returns the record's query name + std::string Name() const; + + /// Sets the record's "query name". + /// + /// \param name new name + /// \returns reference to this record + /// + BamRecordImpl& Name(const std::string& name); + + /// \returns the record's quality values (phred-style ASCII) + /// + /// \note Usually Qualities().size() == Sequence.size(). However, in + /// some data sets, the quality values are not provided. In that + /// case, this method will return an empty container. + /// + QualityValues Qualities() const; + + /// \returns the record's DNA sequence. + std::string Sequence() const; + + size_t SequenceLength() const; + + /// \brief Sets the record's DNA sequence and quality values + /// + /// This is an overloaded function. Sets the DNA sequence and quality + /// values, using the length of \p sequence. + /// + /// \note When using this overload (and \p qualities is non-empty), the + /// lengths of \p sequence and \p qualities \b must be equal. + /// + /// \todo How to handle mismatched lengths? + /// + /// \param[in] sequence std::string containing DNA sequence + /// \param[in] qualities std::string containing ASCII quality values + /// + /// \returns reference to this record. + /// + /// \sa SetSequenceAndQualities(const char* sequence, + /// const size_t sequenceLength, const char* qualities) + /// + BamRecordImpl& SetSequenceAndQualities(const std::string& sequence, + const std::string& qualities = std::string()); + + /// \brief Sets the record's DNA sequence and quality values. + /// + /// The \p sequence must consist of IUPAC nucleotide codes {=ACMGRSVTWYHKDBN}. + /// The \p qualities, if not empty, must consist of 'phred'-style ASCII + /// quality values. \p qualities may be an empty string or NULL pointer in + /// cases where there are no such data available. + /// + /// \param[in] sequence C-string containing DNA sequence + /// \param[in] sequenceLength length of DNA sequence + /// \param[in] qualities C-string containing 'phred-style' ASCII + /// quality values + /// + /// \note \p sequence does \b NOT have to be NULL-terminated. Length is + /// explicitly determined by the value of \p sequenceLength provided. + /// + /// \returns reference to this record. + /// + BamRecordImpl& SetSequenceAndQualities(const char* sequence, const size_t sequenceLength, + const char* qualities = nullptr); + + /// \brief Sets the record's DNA sequence and quality values. + /// + /// The \p encodedSequence should be preencoded/packed into the BAM binary + /// format. The \p qualities, if not empty, must consist of 'phred'-style + /// ASCII quality values. \p qualities may be an empty string or NULL + /// pointer in cases where there are no such data available. + /// + /// \param[in] encodedSequence C-string containing BAM-format-encoded + /// DNA sequence + /// \param[in] rawSequenceLength length of DNA sequence (not the encoded + /// length) + /// \param[in] qualities C-string containing 'phred-style' ASCII + /// quality values + /// + /// \note \p encodedSequence does \b NOT have to be NULL-terminated. Length + /// is explicitly determined by the value of \p sequenceLength + /// provided. + /// + /// \returns reference to this record. + /// + /// \sa SetSequenceAndQualities(const char* sequence, + /// const size_t sequenceLength, const char* qualities) + /// + BamRecordImpl& SetPreencodedSequenceAndQualities(const char* encodedSequence, + const size_t rawSequenceLength, + const char* qualities = nullptr); + + /// \} + +public: + /// \name Tag Data + /// \{ + + /// \returns record's full tag data as a TagCollection object + TagCollection Tags() const; + + /// \brief Sets the record's full tag data via a TagCollection object + /// + BamRecordImpl& Tags(const TagCollection& tags); + + /// \brief Adds a new tag to this record. + /// + /// \param[in] tagName 2-character tag name. + /// \param[in] value Tag object that describes the type & value of data + /// to be added + /// + /// \note Any value that can be used to implicitly construct a Tag is valid. + /// \code + /// string s; + /// vector v; + /// record.AddTag("XX", s); // will add a string-type tag + /// record.AddTag("YY", v); // will add a uint32-array-type tag + /// \endcode + /// + /// \returns true if tag was successfully added. + /// + bool AddTag(const std::string& tagName, const Tag& value); + + /// \brief Adds a new tag to this record. + /// + /// This is an overloaded method. + /// + /// \param[in] tag BamRecordTag enum + /// \param[in] value Tag object that describes the type & value of data + /// to be added + /// \returns true if tag was successfully added. + /// + bool AddTag(const BamRecordTag tag, const Tag& value); + + /// \brief Adds a new tag to this record, with an optional modifier. + /// + /// \param[in] tagName 2-character tag name. + /// \param[in] value Tag object that describes the type & + /// value of data to be added + /// \param[in] additionalModifier optional extra modifier (for explicit + /// modification of an otherwise const Tag) + /// + /// \note Any value that can be used to implicitly construct a Tag is valid. + /// \code + /// char c; + /// string h; + /// record.AddTag("XX", c, TagModifier::ASCII_CHAR); // will add a char-type tag + /// record.AddTag("YY", h, TagModifier::HEX_STRING); // will add a hex string-type tag + /// \endcode + /// + /// \returns true if tag was successfully added. + /// + bool AddTag(const std::string& tagName, const Tag& value, const TagModifier additionalModifier); + + /// \brief Adds a new tag to this record, with an optional modifier. + /// + /// This is an overloaded method. + /// + /// \param[in] tag BamRecordTag enum. + /// \param[in] value Tag object that describes the type & + /// value of data to be added + /// \param[in] additionalModifier optional extra modifier (for explicit + /// modification of an otherwise const Tag) + /// + /// \returns true if tag was successfully added. + /// + bool AddTag(const BamRecordTag tag, const Tag& value, const TagModifier additionalModifier); + + /// \brief Edits an existing tag on this record. + /// + /// \param[in] tagName 2-character tag name. Name must be present + /// (see HasTag) + /// \param[in] newValue Tag object that describes the type & value of + /// new data to be added + /// + /// \note Any value that can be used to implicitly construct a Tag is valid. + /// \code + /// string s; + /// vector v; + /// record.EditTag("XX", s); // will overwrite tag XX with a string-type tag + /// record.EditTag("YY", v); // will overwrite tag YY with a uint32-array-type tag + /// \endcode + /// + /// \returns true if tag was successfully edited. + /// + bool EditTag(const std::string& tagName, const Tag& newValue); + + /// \brief Edits an existing tag on this record. + /// + /// This is an overloaded method. + /// + /// \param[in] tag BamRecordTag enum + /// \param[in] newValue Tag object that describes the type & value of + /// new data to be added + /// + /// \returns true if tag was successfully edited. + /// + bool EditTag(const BamRecordTag tag, const Tag& newValue); + + /// \brief Edits an existing tag on this record. + /// + /// \param[in] tagName 2-character tag name. Name must be + /// present (see HasTag) + /// \param[in] value Tag object that describes the type & + /// value of new data to be added + /// \param[in] additionalModifier optional extra modifier (for explicit + /// modification of an otherwise const Tag) + /// + /// \note Any value that can be used to implicitly construct a Tag is valid. + /// \code + /// char c; + /// string h; + /// record.EditTag("XX", c, TagModifier::ASCII_CHAR); // will overwrite tag XX with a char-type tag + /// record.EditTag("YY", h, TagModifier::HEX_STRING); // will overwrite tag YY with a hex string-type tag + /// \endcode + /// + /// \returns true if tag was successfully edited. + /// + bool EditTag(const std::string& tagName, const Tag& value, + const TagModifier additionalModifier); + + /// \brief Edits an existing tag on this record. + /// + /// This is an overloaded method. + /// + /// \param[in] tag BamRecordTag enum + /// \param[in] value Tag object that describes the type & + /// value of new data to be added + /// \param[in] additionalModifier optional extra modifier (for explicit + /// modification of an otherwise const Tag) + /// + /// \returns true if tag was successfully edited. + /// + bool EditTag(const BamRecordTag tag, const Tag& value, const TagModifier additionalModifier); + + /// \returns true if a tag with this name is present in this record. + bool HasTag(const std::string& tagName) const; + + /// \returns true if this tag is present in this record. + /// + /// This is an overloaded method. + /// + bool HasTag(const BamRecordTag tag) const; + + /// \brief Removes an existing tag from this record. + /// + /// \param[in] tagName 2-character tag name. + /// + /// \returns true if tag was actaully removed (i.e. false if tagName + /// previously unknown) + /// \sa HasTag + /// + bool RemoveTag(const std::string& tagName); + + /// \brief Removes an existing tag from this record. + /// + /// This is an overloaded method. + /// + /// \param[in] tag BamRecordTag enum + /// + /// \returns true if tag was actaully removed (i.e. false if tagName + /// previously unknown) + /// \sa HasTag + /// + bool RemoveTag(const BamRecordTag tag); + + /// \brief Fetches a tag from this record. + /// + /// \param[in] tagName 2-character tag name. + /// + /// \returns Tag object for the requested name. If name is unknown, a + /// default constructed Tag is returned (Tag::IsNull() is true). + /// + Tag TagValue(const std::string& tagName) const; + + /// \brief Fetches a tag from this record. + /// + /// This is an overloaded method + /// + /// \param[in] tag BamRecordTag enum + /// + /// \returns Tag object for the requested name. If name is unknown, a + /// default constructed Tag is returned (Tag::IsNull() is true). + /// + Tag TagValue(const BamRecordTag tag) const; + + // change above to Tag(); + + // template + // T TagValue(const std::string& tagName) const; + + /// \} + +private: + // returns a BamRecordImpl object, with a deep copy of @rawData contents + static BamRecordImpl FromRawData(const std::shared_ptr& rawData); + + // internal memory setup/expand methods + void InitializeData(); + void MaybeReallocData(); + void UpdateTagMap() const; // allowed to be called from const methods + // (lazy update on request) + + // internal tag helper methods + bool AddTagImpl(const std::string& tagName, const Tag& value, + const TagModifier additionalModifier); + bool RemoveTagImpl(const std::string& tagName); + + int TagOffset(const std::string& tagName) const; + + // internal CIGAR handling + void SetCigarData(const Cigar& cigar); + + // core seq/qual logic shared by the public API + BamRecordImpl& SetSequenceAndQualitiesInternal(const char* sequence, + const size_t sequenceLength, + const char* qualities, bool isPreencoded); + +private: + // data members + std::shared_ptr d_; + mutable std::unordered_map tagOffsets_; + + // friends + friend class BamRecordMemory; + + // remove this when we drop support for htslib pre-v1.7 + friend class SamWriter; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMRECORDIMPL_H diff --git a/include/pbbam/BamRecordTag.h b/include/pbbam/BamRecordTag.h new file mode 100644 index 0000000..35ce216 --- /dev/null +++ b/include/pbbam/BamRecordTag.h @@ -0,0 +1,64 @@ +// File Description +/// \file BamRecordTag.h +/// \brief Defines the BamRecordTag enum. +// +// Author: Derek Barnett + +#ifndef BAMRECORDTAG_H +#define BAMRECORDTAG_H + +#include "pbbam/Config.h" + +namespace PacBio { +namespace BAM { + +enum class BamRecordTag +{ + ALT_LABEL_QV, + ALT_LABEL_TAG, + BARCODE_QUALITY, + BARCODES, + CONTEXT_FLAGS, + DELETION_QV, + DELETION_TAG, + HOLE_NUMBER, + INSERTION_QV, + IPD, + LABEL_QV, + LONG_CIGAR, + MERGE_QV, + NUM_PASSES, + PKMEAN, + PKMEAN_2, + PKMID, + PKMID_2, + PRE_PULSE_FRAMES, + PULSE_CALL, + PULSE_CALL_WIDTH, + PULSE_EXCLUSION, + PULSE_MERGE_QV, + PULSE_WIDTH, + QUERY_END, + QUERY_END_FRAME_NUMBER, + QUERY_START, + QUERY_START_FRAME_NUMBER, + READ_ACCURACY, + READ_GROUP, + SCRAP_REGION_TYPE, + SCRAP_ZMW_TYPE, + SIGNAL_TO_NOISE, + START_FRAME, + SUBSTITUTION_QV, + SUBSTITUTION_TAG, + + // + // not tags per se, but faking these here to simplify data fetching + // + QUAL, + SEQ +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMRECORDTAG_H diff --git a/include/pbbam/BamRecordView.h b/include/pbbam/BamRecordView.h new file mode 100644 index 0000000..7fe56f9 --- /dev/null +++ b/include/pbbam/BamRecordView.h @@ -0,0 +1,132 @@ +// File Description +/// \file BamRecordView.h +/// \brief Defines the BamRecordView class. +// +// Author: Derek Barnett + +#ifndef BAMRECORDVIEW_H +#define BAMRECORDVIEW_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/BamRecord.h" + +namespace PacBio { +namespace BAM { + +/// \brief Provides a re-usable "view" onto a BamRecord +/// +/// This class acts a convenience wrapper for working with per-base BamRecord +/// data. Most of these BamRecord methods take a list of parameters, to adjust +/// how the underlying data are presented to client code. Often these parameters +/// will be re-used for each BamRecord method call. Thus, to simplify such +/// client code, a BamRecordView can be used to state those parameters once, and +/// then simply request the desired fields. +/// +/// \internal +/// \todo Sync up method names with BamRecord +/// \endinternal +/// +class PBBAM_EXPORT BamRecordView +{ +public: + /// \brief Constructs a view onto \p record using the supplied parameters. + /// + /// For frame or QV data, if \p aligned is true, a value of 0 (Accuracy or + /// QualityValue) will be used at each inserted or padded base location. + /// + /// \param[in] record BamRecord data source. + /// \param[in] orientation Orientation of output. + /// \param[in] aligned if true, gaps/padding will be inserted, per + /// Cigar info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + BamRecordView(const BamRecord& record, const Orientation orientation, const bool aligned, + const bool exciseSoftClips, + const PulseBehavior pulseBehavior = PulseBehavior::ALL); + +public: + /// \returns BamRecord::AltLabelQV with this view's parameters applied + QualityValues AltLabelQVs() const; + + /// \returns BamRecord::AltLabelTag with this view's parameters applied + std::string AltLabelTags() const; + + /// \returns BamRecord::DeletionQV with this view's parameters applied + QualityValues DeletionQVs() const; + + /// \returns BamRecord::DeletionTag with this view's parameters applied + std::string DeletionTags() const; + + /// \returns BamRecord::InsertionQV with this view's parameters applied + QualityValues InsertionQVs() const; + + /// \returns BamRecord::IPD with this view's parameters applied + Frames IPD() const; + + /// \returns BamRecord::LabelQV with this view's parameters applied + QualityValues LabelQVs() const; + + /// \returns BamRecord::MergeQV with this view's parameters applied + QualityValues MergeQVs() const; + + /// \returns BamRecord::PulseMergeQV with this view's parameters applied + QualityValues PulseMergeQVs() const; + + /// \returns BamRecord::Pkmean with this view's parameters applied + std::vector Pkmean() const; + + /// \returns BamRecord::Pkmid with this view's parameters applied + std::vector Pkmid() const; + + /// \returns BamRecord::Pkmean2 with this view's parameters applied + std::vector Pkmean2() const; + + /// \returns BamRecord::Pkmid2 with this view's parameters applied + std::vector Pkmid2() const; + + /// \returns BamRecord::PreBaseFrames with this view's parameters applied + Frames PrebaseFrames() const; + + /// \returns BamRecord::PrePulseFrames with this view's parameters applied + Frames PrePulseFrames() const; + + /// \returns BamRecord::PulseCalls with this view's parameters applied + std::string PulseCalls() const; + + /// \returns BamRecord::PulseCallWidth with this view's parameters applied + Frames PulseCallWidth() const; + + /// \returns BamRecord::PulseWidths with this view's parameters applied + Frames PulseWidths() const; + + /// \returns BamRecord::Qualities with this view's parameters applied + QualityValues Qualities() const; + + /// \returns BamRecord::Sequence with this view's parameters applied + std::string Sequence() const; + + /// \returns BamRecord::StartFrame with this view's parameters applied + std::vector StartFrames() const; + + /// \returns BamRecord::SubstitutionQV with this view's parameters applied + QualityValues SubstitutionQVs() const; + + /// \returns BamRecord::SubstitutionTag with this view's parameters applied + std::string SubstitutionTags() const; + +private: + const BamRecord& record_; + Orientation orientation_; + bool aligned_; + bool exciseSoftClips_; + PulseBehavior pulseBehavior_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMRECORDVIEW_H diff --git a/include/pbbam/BamTagCodec.h b/include/pbbam/BamTagCodec.h new file mode 100644 index 0000000..6847d95 --- /dev/null +++ b/include/pbbam/BamTagCodec.h @@ -0,0 +1,92 @@ +// File Description +/// \file BamTagCodec.h +/// \brief Defines the BamTagCodec class. +// +// Author: Derek Barnett + +#ifndef BAMTAGCODEC_H +#define BAMTAGCODEC_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/TagCollection.h" + +namespace PacBio { +namespace BAM { + +/// \brief The BamTagCodec class provides binary encoding/decoding of %BAM tag +/// data. +/// +/// \note BamTagCodec is mostly an implementation and/or testing detail, and may +/// be removed from the public API. +/// +class PBBAM_EXPORT BamTagCodec +{ +public: + /// \name Tag Collection Methods + /// \{ + + /// \brief Creates a TagCollection from raw BAM data. + /// + /// \param[in] data BAM-formatted (binary) tag data + /// \returns TagCollection containing tag data + /// + static TagCollection Decode(const std::vector& data); + + /// \brief Creates binary BAM data from a TagCollection. + /// + /// \param[in] tags TagCollection containing tag data + /// \returns vector of bytes (encoded BAM data) + /// + static std::vector Encode(const PacBio::BAM::TagCollection& tags); + + /// \} + +public: + /// \name Per-Tag Methods + /// \{ + + /// \brief Determines the SAM/BAM tag code for a Tag. + /// + /// \param[in] tag Tag object to check + /// \param[in] additionalModifier optional extra modifier (allows explicit + /// modification of an otherwise const Tag) + /// + /// \returns the SAM/BAM single char code for tag type + /// + static uint8_t TagTypeCode(const PacBio::BAM::Tag& tag, + const TagModifier& additionalModifier = TagModifier::NONE); + + /// \brief Encodes a single Tag's contents in %BAM binary + /// + /// \note This method does \b NOT encode the tag name & tag type. It does + /// include the element type for array-type tags. + /// + /// \param[in] tag Tag object containing data to encode + /// \param[in] additionalModifier optional extra modifier (allows explicit + /// modification of an otherwise const Tag) + /// + /// \returns vector of bytes (encoded BAM data) + /// + static std::vector ToRawData( + const PacBio::BAM::Tag& tag, const TagModifier& additionalModifier = TagModifier::NONE); + + /// \brief Creates a Tag object from binary BAM data. + /// + /// \param[in] rawData raw BAM bytes (assumed to be the result of + /// htslib's bam_aux_get()) + /// + /// \returns resulting Tag object + /// + static PacBio::BAM::Tag FromRawData(uint8_t* rawData); + + /// \} +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMTAGCODEC_H diff --git a/include/pbbam/BamWriter.h b/include/pbbam/BamWriter.h new file mode 100644 index 0000000..60945d8 --- /dev/null +++ b/include/pbbam/BamWriter.h @@ -0,0 +1,220 @@ +// File Description +/// \file BamWriter.h +/// \brief Defines the BamWriter class. +// +// Author: Derek Barnett + +#ifndef BAMWRITER_H +#define BAMWRITER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/IRecordWriter.h" + +namespace PacBio { +namespace BAM { + +class BamFile; + +/// \brief The BamWriter class provides a writing interface for creating +/// new %BAM files. +/// +/// \note The underlying buffered data may not be flushed to the file until the +/// destructor is called. Trying to access the file (reading, stat-ing, +/// indexing, etc.) before the BamWriter is destroyed yields undefined +/// behavior. Enclose the BamWriter in some form of local scope (curly +/// braces, a separate function, etc.) to ensure that its destructor is +/// called before proceeding to read-based operations. +/// +/// \code{.cpp} +/// { +/// BamWriter w(...); +/// // write data +/// } +/// // now safe to access the new file +/// \endcode +/// +/// +class PBBAM_EXPORT BamWriter : public IRecordWriter +{ +public: + /// \brief This enum allows you to control the compression level of the + /// output %BAM file. + /// + /// Values are equivalent to zlib compression levels. See its documentation + /// for more details: http://www.zlib.net/manual.html + /// + enum CompressionLevel + { + CompressionLevel_0 = 0, + CompressionLevel_1 = 1, + CompressionLevel_2 = 2, + CompressionLevel_3 = 3, + CompressionLevel_4 = 4, + CompressionLevel_5 = 5, + CompressionLevel_6 = 6, + CompressionLevel_7 = 7, + CompressionLevel_8 = 8, + CompressionLevel_9 = 9, + + DefaultCompression = -1, + NoCompression = CompressionLevel_0, + FastCompression = CompressionLevel_1, + BestCompression = CompressionLevel_9 + }; + + /// \brief This enum allows you to control whether BAI bin numbers are + /// calculated for output records. + /// + /// For most cases, the default behavior (ON) should be retained for maximum + /// compatibility with downstream tools (e.g. samtools index). Disabling bin + /// calculation should only be used if all records are known to never be + /// mapped, and even then only if profiling revelas the calculation to + /// affect extremely performance-sensitive, "critical paths". + /// + enum BinCalculationMode + { + BinCalculation_ON = 0, + BinCalculation_OFF + }; + + /// + /// \brief The Config struct provides a "parameter object" for BamWriter + /// settings. This allows for writer configuration without having to + /// refer to ordering of parameters, default values, etc. + /// + struct Config + { + // zlib compression level + CompressionLevel compressionLevel = DefaultCompression; + + // The number of threads for compression. If set to 0, BamWriter will + // attempt to determine a reasonable estimate. If set to 1, this will + // force single-threaded execution. No checks are made against an upper limit. + size_t numThreads = 4; + + // If ON, ensures that proper BAI bin numbers are provided for all records. + BamWriter::BinCalculationMode binCalculationMode = BamWriter::BinCalculation_ON; + + // If true, write to .tmp, and rename to in dtor. + // This allows downstream checks to see if BAM file may be truncated + // due to early termination (e.g. a thrown exception). If false, write + // directly to . + bool useTempFile = true; + }; + +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Opens a %BAM file for writing & writes the header information. + /// + /// \note Set \p filename to "-" for stdout. + /// + /// \param[in] filename path to output %BAM file + /// \param[in] header BamHeader object + /// \param[in] compressionLevel zlib compression level + /// \param[in] numThreads number of threads for compression. If set to + /// 0, BamWriter will attempt to determine a + /// reasonable estimate. If set to 1, this will + /// force single-threaded execution. No checks + /// are made against an upper limit. + /// + /// \param[in] binCalculationMode BAI bin calculation mode. The default + /// behavior will ensure proper bin numbers are provided for all + /// records written. This extra step may turned off when bin + /// numbers are not needed. Though if in doubt, keep the default. + /// + /// \param[in] useTempFile If true, write to .tmp, and rename + /// to . This provides for downstream + /// checks to see if BAM file may be truncated + /// due to early termination (a thrown exception). + /// + /// \throws std::runtmie_error if there was a problem opening the file for + /// writing or if an error occurred while writing the header + /// + BamWriter(const std::string& filename, const BamHeader& header, + const BamWriter::CompressionLevel compressionLevel = BamWriter::DefaultCompression, + const size_t numThreads = 4, + const BinCalculationMode binCalculationMode = BamWriter::BinCalculation_ON, + const bool useTempFile = true); + + /// + /// \brief Opens a %BAM file for writing & writes the header information. + /// + /// \param[in] filename path to output %BAM file + /// \param[in] header BamHeader object + /// \param[in] config container for add'l configuration options + /// + /// \throws std::runtmie_error if there was a problem opening the file for + /// writing or if an error occurred while writing the header + /// + BamWriter(const std::string& filename, const BamHeader& header, + const BamWriter::Config& config); + + BamWriter(BamWriter&&) noexcept; + BamWriter& operator=(BamWriter&&) noexcept; + + /// Fully flushes all buffered data & closes file. + ~BamWriter() override; + + /// \} + +public: + /// \name Data Writing & Resource Management + /// \{ + + /// \brief Try to flush any buffered data to file. + /// + /// \note The underlying implementation doesn't necessarily flush buffered + /// data immediately, especially in a multithreaded writer situation. + /// Let the BamWriter go out of scope to fully ensure flushing. + /// + /// \throws std::runtime_error if flush fails + /// + void TryFlush() override; + + /// \brief Write a record to the output %BAM file. + /// + /// \param[in] record BamRecord object + /// + /// \throws std::runtime_error on failure to write + /// + void Write(const BamRecord& record) override; + + /// \brief Write a record to the output %BAM file. + /// + /// \param[in] record BamRecord object + /// \param[out] vOffset BGZF virtual offset to start of \p record + /// + /// \throws std::runtime_error on failure to write + /// + void Write(const BamRecord& record, int64_t* vOffset); + + /// \brief Write a record to the output %BAM file. + /// + /// \param[in] recordImpl BamRecordImpl object + /// + /// \throws std::runtime_error on failure to write + /// + void Write(const BamRecordImpl& recordImpl) override; + + /// \} + +private: + class BamWriterPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BAMWRITER_H diff --git a/include/pbbam/BarcodeQuery.h b/include/pbbam/BarcodeQuery.h new file mode 100644 index 0000000..29f7511 --- /dev/null +++ b/include/pbbam/BarcodeQuery.h @@ -0,0 +1,64 @@ +// File Description +/// \file BarcodeQuery.h +/// \brief Defines the BarcodeQuery class. +// +// Author: Derek Barnett + +#ifndef BARCODEQUERY_H +#define BARCODEQUERY_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The BarcodeQuery class provides iterable access to a DataSet's %BAM +/// records, limiting results to those matching a particular barcode. +/// +/// Example: +/// \include code/BarcodeQuery.txt +/// +/// \note Currently, all %BAM files must have a corresponding ".pbi" index file. +/// Use BamFile::EnsurePacBioIndexExists before creating the query if one +/// may not be present. +/// +class PBBAM_EXPORT BarcodeQuery : public internal::IQuery +{ +public: + /// \brief Creates a new BarcodeQuery, limiting record results to only those + /// annotated with a particular barcode ID. + /// + /// \param[in] barcode filtering criteria + /// \param[in] dataset input data source(s) + /// + /// \sa BamRecord::Barcodes + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or PBI + /// files. + /// + BarcodeQuery(const int16_t barcode, const DataSet& dataset); + + ~BarcodeQuery() override; + +public: + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(BamRecord& r) override; + +private: + class BarcodeQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BARCODEQUERY_H diff --git a/include/pbbam/BgzipFastaWriter.h b/include/pbbam/BgzipFastaWriter.h new file mode 100644 index 0000000..48408cf --- /dev/null +++ b/include/pbbam/BgzipFastaWriter.h @@ -0,0 +1,47 @@ +// File Description +/// \file BgzipFastaWriter.h +/// \brief Defines the BgzipFastaWriter class. +// +// Author: Derek Barnett + +#ifndef BGZIPFASTAWRITER_H +#define BGZIPFASTAWRITER_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/BgzipWriter.h" +#include "pbbam/IFastaWriter.h" + +namespace PacBio { +namespace BAM { + +class BamRecord; +class BamRecordImpl; +class FastaSequence; + +class BgzipFastaWriter final : public IFastaWriter +{ +public: + explicit BgzipFastaWriter(const std::string& fn); + BgzipFastaWriter(const std::string& fn, const BgzipWriterConfig& config); + +public: + // IFastaWriter + void Write(const FastaSequence& fastq); + void Write(const std::string& name, const std::string& bases); + + // IRecordWriter + void TryFlush(); + void Write(const BamRecord& bam); + void Write(const BamRecordImpl& bam); + +private: + BgzipWriter writer_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BGZIPFASTAWRITER_H diff --git a/include/pbbam/BgzipFastqWriter.h b/include/pbbam/BgzipFastqWriter.h new file mode 100644 index 0000000..53cfc94 --- /dev/null +++ b/include/pbbam/BgzipFastqWriter.h @@ -0,0 +1,50 @@ +// File Description +/// \file BgzipFastqWriter.h +/// \brief Defines the BgzipFastqWriter class. +// +// Author: Derek Barnett + +#ifndef BGZIPFASTQWRITER_H +#define BGZIPFASTQWRITER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/BgzipWriter.h" +#include "pbbam/IFastqWriter.h" + +namespace PacBio { +namespace BAM { + +class BamRecord; +class BamRecordImpl; +class FastqSequence; + +class BgzipFastqWriter final : public IFastqWriter +{ +public: + explicit BgzipFastqWriter(const std::string& fn); + BgzipFastqWriter(const std::string& fn, const BgzipWriterConfig& config); + +public: + // IFastqWriter + void Write(const FastqSequence& fastq); + void Write(const std::string& name, const std::string& bases, const QualityValues& quals); + void Write(const std::string& name, const std::string& bases, const std::string& quals); + + // IRecordWriter + void TryFlush(); + void Write(const BamRecord& bam); + void Write(const BamRecordImpl& bam); + +private: + BgzipWriter writer_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BGZFFASTQWRITER_H diff --git a/include/pbbam/BgzipWriter.h b/include/pbbam/BgzipWriter.h new file mode 100644 index 0000000..30c9213 --- /dev/null +++ b/include/pbbam/BgzipWriter.h @@ -0,0 +1,81 @@ +// File Description +/// \file BgzipWriter.h +/// \brief Defines the BgzipWriter class. +// +// Author: Derek Barnett + +#ifndef BGZIPWRITER_H +#define BGZIPWRITER_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +struct BgzipWriterConfig +{ + // Compression level, equivalent to zlib-defined levels + const size_t CompressionLevel = 0; + + /// Nnumber of threads for compression. If set to 0, the writer will attempt + /// to determine a reasonable estimate. If set to 1, this will force + /// single-threaded execution. No checks are made against an upper limit. + const size_t NumThreads = 4; + + /// If true, write to .tmp, and rename to on closing. + /// This provides for downstream checks to see if the file may be truncated + /// due to early termination (e.g. a thrown exception). + const bool UseTempFile = true; +}; + +/// \brief The BgzipWriter writes BGZF-compressed data to a file. +/// +class PBBAM_EXPORT BgzipWriter +{ +public: + /// + /// Create a BgzipWriter, using default configuration parameters. + /// + explicit BgzipWriter(std::string filename); + + /// + /// Create a BgzipWriter, using configuration provided. + /// + BgzipWriter(std::string filename, const BgzipWriterConfig& config); + + BgzipWriter(BgzipWriter&&) noexcept; + BgzipWriter& operator=(BgzipWriter&&) noexcept; + ~BgzipWriter(); + +public: + /// + /// \brief Writes raw bytes to BGZF file. + /// + /// \param data data buffer + /// \param numBytes num bytes (data size * sizeof(T)) + /// + /// \returns number of bytes written + /// + size_t Write(const void* data, size_t numBytes); + + /// + /// \brief Writes string data to BGZF file. + /// + /// \param data data string + /// + /// \returns number of bytes written + /// + size_t Write(const std::string& data); + +private: + class BgzipWriterPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BGZIPWRITER_H diff --git a/include/pbbam/Cigar.h b/include/pbbam/Cigar.h new file mode 100644 index 0000000..f3529d8 --- /dev/null +++ b/include/pbbam/Cigar.h @@ -0,0 +1,29 @@ +// File Description +/// \file Cigar.h +/// \brief Defines the Cigar class. +// +// Author: Derek Barnett + +#ifndef CIGAR_H +#define CIGAR_H + +#include "pbbam/Config.h" + +#include +#include + +#include + +#include "pbbam/CigarOperation.h" + +namespace PacBio { +namespace BAM { + +using Cigar PBBAM_DEPRECATED = PacBio::Data::Cigar; + +PBBAM_DEPRECATED constexpr auto ReferenceLength = PacBio::Data::ReferenceLength; + +} // namespace BAM +} // namespace PacBio + +#endif // CIGAR_H diff --git a/include/pbbam/CigarOperation.h b/include/pbbam/CigarOperation.h new file mode 100644 index 0000000..17f4709 --- /dev/null +++ b/include/pbbam/CigarOperation.h @@ -0,0 +1,29 @@ +// File Description +/// \file CigarOperation.h +/// \brief Defines the CigarOperationType enum & CigarOperation class. +// +// Author: Derek Barnett + +#ifndef CIGAROPERATION_H +#define CIGAROPERATION_H + +#include "pbbam/Config.h" + +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +using CigarOperation PBBAM_DEPRECATED = PacBio::Data::CigarOperation; +using CigarOperationType PBBAM_DEPRECATED = PacBio::Data::CigarOperationType; + +PBBAM_DEPRECATED constexpr auto ConsumesQuery = PacBio::Data::ConsumesQuery; +PBBAM_DEPRECATED constexpr auto ConsumesReference = PacBio::Data::ConsumesReference; + +} // namespace BAM +} // namespace PacBio + +#endif // CIGAROPERATION_H diff --git a/include/pbbam/ClipType.h b/include/pbbam/ClipType.h new file mode 100644 index 0000000..cc48176 --- /dev/null +++ b/include/pbbam/ClipType.h @@ -0,0 +1,32 @@ +// File Description +/// \file ClipType.h +/// \brief Defines the ClipType enum. +// +// Author: Derek Barnett + +#ifndef CLIPTYPE_H +#define CLIPTYPE_H + +#include "pbbam/Config.h" + +namespace PacBio { +namespace BAM { + +/// \brief This enum defines the modes supported by BamRecord clipping +/// operations. +/// +/// Methods like BamRecord::Clip accept Position parameters - which may be in +/// either polymerase or reference coorindates. Using this enum as a flag +/// indicates how the positions should be interpreted. +/// +enum class ClipType +{ + CLIP_NONE, ///< No clipping will be performed. + CLIP_TO_QUERY, ///< Clipping positions are in polymerase coordinates. + CLIP_TO_REFERENCE ///< Clipping positions are in genomic coordinates. +}; + +} // namespace BAM +} // namespace PacBio + +#endif // CLIPTYPE_H diff --git a/include/pbbam/Compare.h b/include/pbbam/Compare.h new file mode 100644 index 0000000..d87ffb2 --- /dev/null +++ b/include/pbbam/Compare.h @@ -0,0 +1,471 @@ +// File Description +/// \file Compare.h +/// \brief Defines the Compare class & a number of function objects for +/// comparing BamRecords. +// +// Author: Derek Barnett + +#ifndef COMPARE_H +#define COMPARE_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include "pbbam/BamRecord.h" + +namespace PacBio { +namespace BAM { + +/// \brief The Compare class provides utilities for sorting collections of +/// BamRecords. +/// +/// \note The functors provided here currently only support std::less +/// comparisons (i.e. sorting by ascending value). +/// +/// \include code/Compare.txt +/// +struct PBBAM_EXPORT Compare +{ +public: + /// \name Comparison Type + /// \{ + + /// \brief This enum defines the supported comparison types + /// { ==, !=, <, <=, >, >=, & (contains), ~ (not contains) }. + /// + enum Type + { + EQUAL = 0, + NOT_EQUAL, + LESS_THAN, + LESS_THAN_EQUAL, + GREATER_THAN, + GREATER_THAN_EQUAL, + CONTAINS, + NOT_CONTAINS + }; + + /// \brief Convert operator string to Compare::Type. + /// + /// \include code/Compare_TypeFromOperator.txt + /// + /// \param[in] opString operator string. Can be C++-style operators + /// ("==", "!=", "<=", etc) or alpha equivalents + /// ("eq", "ne", "lte", etc). + /// + /// \returns comparison type from an operator string + /// \throws std::runtime_error if cannot convert opString to Compare::Type + /// \sa Compare::TypeToOperator + /// + static Compare::Type TypeFromOperator(const std::string& opString); + + /// \brief Convert a Compare::Type to printable enum name. + /// + /// \include code/Compare_TypeToName.txt + /// + /// \param[in] type Compare::Type to convert + /// \returns the printable name for a Compare::Type enum value.are::Type + /// \throws std::runtime_error on unknown Compare::Type + /// + static std::string TypeToName(const Compare::Type& type); + + /// \brief Convert a Compare::Type to printable operator. + /// + /// \param[in] type Compare::Type to convert + /// \param[in] asAlpha (optional) flag to print using alpha equivalents + /// e.g. "lte" rather than "<=" + /// \returns the printable operator string + /// \throws std::runtime_error on unknown Compare::Type + /// + static std::string TypeToOperator(const Compare::Type& type, bool asAlpha = false); + + /// \} + +public: + /// \name Comparison Function Objects + /// \{ + + /// %Base class for all BamRecord compare functors. + /// + /// Mostly used for method signatures that can accept any comparator. + /// + /// Custom comparators may be used by inheriting from this class. + /// + struct Base : public std::function + { + }; + +private: + /// \internal + /// + /// Exists to provide the typedef we'll use in the actual + /// MemberFunctionBase, since we need to use it in the template signature. + /// This keeps that a lot easier to read. + /// + template + struct MemberFunctionBaseHelper : public Compare::Base + { + using MemberFnType = ValueType (BamRecord::*)() const; + }; + +public: + /// \brief %Base class for all BamRecord compare functors that take a + /// BamRecord function pointer and compare on its return type. + /// + /// Derived comparators usually need only declare the return value & + /// function pointer in the template signature. This class implements the + /// basic method-calling machinery. + /// + /// Custom comparators will work for any BamRecord member function that does + /// not take any input parameters. + /// + template ::MemberFnType fn, + typename CompareType = std::less > + struct MemberFunctionBase : public Compare::MemberFunctionBaseHelper + { + bool operator()(const BamRecord& lhs, const BamRecord& rhs) const; + }; + +public: + /// \brief Compares on BamRecord::AlignedEnd. + /// + /// Example: + /// \include code/Compare_AlignedEnd.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct AlignedEnd : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::AlignedStart. + /// + /// Example: + /// \include code/Compare_AlignedStart.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct AlignedStart : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::AlignedStrand + /// + /// Example: + /// \include code/Compare_AlignedStrand.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct AlignedStrand : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::BarcodeForward. + /// + /// Example: + /// \include code/Compare_BarcodeForward.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct BarcodeForward : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::BarcodeQuality. + /// + /// Example: + /// \include code/Compare_BarcodeQuality.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct BarcodeQuality : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::BarcodeReverse. + /// + /// Example: + /// \include code/Compare_BarcodeReverse.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct BarcodeReverse : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::FullName. + /// + /// Example: + /// \include code/Compare_FullName.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct FullName : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::LocalContextFlags. + /// + /// Example: + /// \include code/Compare_LocalContextFlag.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct LocalContextFlag + : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::MapQuality. + /// + /// Example: + /// \include code/Compare_MapQuality.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct MapQuality : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::MovieName. + /// + /// Example: + /// \include code/Compare_MovieName.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct MovieName : public MemberFunctionBase + { + }; + + /// \brief Provides an operator() is essentially a no-op for + /// comparing/sorting. + /// + /// If used in a sorting operation, then no change will occur. + /// + struct None : public Compare::Base + { + bool operator()(const BamRecord&, const BamRecord&) const; + }; + + ///\brief Compares on BamRecord::NumDeletedBases. + /// + /// Example: + /// \include code/Compare_NumDeletedBases.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct NumDeletedBases : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::NumInsertedBases. + /// + /// Example: + /// \include code/Compare_NumInsertedBases.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct NumInsertedBases : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::NumMatches. + /// + /// Example: + /// \include code/Compare_NumMatches.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct NumMatches : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::NumMismatches. + /// + /// Example: + /// \include code/Compare_NumMismatches.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct NumMismatches : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::QueryEnd. + /// + /// Example: + /// \include code/Compare_QueryEnd.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct QueryEnd : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::QueryStart. + /// + /// Example: + /// \include code/Compare_QueryStart.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct QueryStart : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::ReadAccuracy. + /// + /// Example: + /// \include code/Compare_ReadAccuracy.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct ReadAccuracy : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::ReadGroupId. + /// + /// \note Even though the ReadGroupId string contains hex values, it is + /// still just a std::string. Comparisons will use lexical, not + /// numeric ordering. If numeric ordering is desired, use + /// Compare::ReadGroupNumericId instead. + /// + /// Example: + /// \include code/Compare_ReadGroupId.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct ReadGroupId : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::ReadGroupNumericId. + /// + /// Example: + /// \include code/Compare_ReadGroupNumericId.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct ReadGroupNumericId : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::ReferenceEnd. + /// + /// Example: + /// \include code/Compare_ReferenceEnd.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct ReferenceEnd : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::ReferenceId. + /// + /// Example: + /// \include code/Compare_ReferenceId.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct ReferenceId : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::ReferenceName. + /// + /// Example: + /// \include code/Compare_ReferenceName.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct ReferenceName : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::ReferenceStart. + /// + /// Example: + /// \include code/Compare_ReferenceStart.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct ReferenceStart : public MemberFunctionBase + { + }; + + /// \brief Compares on BamRecord::HoleNumber. + /// + /// Example: + /// \include code/Compare_Zmw.txt + /// + /// \note Currently only supports std::less comparisons (i.e. sorting by + /// ascending value). + /// + struct Zmw : public MemberFunctionBase + { + }; + + /// \} + + template + static inline bool Check(const T& lhs, const T& rhs, const Compare::Type cmp) + { + switch (cmp) { + case Compare::EQUAL: + case Compare::CONTAINS: + return lhs == rhs; + case Compare::LESS_THAN: + return lhs < rhs; + case Compare::LESS_THAN_EQUAL: + return lhs <= rhs; + case Compare::GREATER_THAN: + return lhs > rhs; + case Compare::GREATER_THAN_EQUAL: + return lhs >= rhs; + case Compare::NOT_EQUAL: + case Compare::NOT_CONTAINS: + return lhs != rhs; + default: + assert(false); + throw std::runtime_error{"unsupported compare type requested"}; + } + } +}; + +} // namespace BAM +} // namespace PacBio + +#include "pbbam/internal/Compare.inl" + +#endif // COMPARE_H diff --git a/include/pbbam/CompositeBamReader.h b/include/pbbam/CompositeBamReader.h new file mode 100644 index 0000000..52bc913 --- /dev/null +++ b/include/pbbam/CompositeBamReader.h @@ -0,0 +1,286 @@ +// File Description +/// \file CompositeBamReader.h +/// \brief Defines the composite BAM readers, for working with multiple input +/// files. +// +// Author: Derek Barnett + +#ifndef COMPOSITEBAMREADER_H +#define COMPOSITEBAMREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include "pbbam/BaiIndexCache.h" +#include "pbbam/BaiIndexedBamReader.h" +#include "pbbam/BamFile.h" +#include "pbbam/BamHeader.h" +#include "pbbam/BamReader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/DataSet.h" +#include "pbbam/GenomicInterval.h" +#include "pbbam/PbiIndexedBamReader.h" + +namespace PacBio { +namespace BAM { + +namespace internal { + +/// \internal +/// \brief The CompositeMergeItem class provides a helper struct for composite +/// readers, containing a single-file reader and its "next" record. +/// +struct CompositeMergeItem +{ +public: + std::unique_ptr reader; + BamRecord record; + +public: + CompositeMergeItem(std::unique_ptr rdr); + CompositeMergeItem(std::unique_ptr rdr, BamRecord rec); +}; + +/// \internal +/// \brief The CompositeMergeItemSorter class provides a helper function object +/// for ordering composite reader results. +/// +/// Essentially just exracts a BamRecord from its parent CompositeMergeItem for +/// further checks. +/// +template +struct CompositeMergeItemSorter + : public std::function +{ + bool operator()(const CompositeMergeItem& lhs, const CompositeMergeItem& rhs) const; +}; + +} // namespace internal + +/// \brief The GenomicIntervalCompositeBamReader class provides read access to +/// multipe %BAM files, limiting results to a genomic region. +/// +/// Requires a ".bai" file for each input %BAM file. +/// +/// Results will be returned in order of genomic coordinate (first by reference +/// ID, then by position). +/// +class PBBAM_EXPORT GenomicIntervalCompositeBamReader +{ +public: + /// \name Contstructors & Related Methods + /// \{ + + /// \brief Constructs composite %BAM reader, that can be queried on genomic interval. + /// + /// \note Using this constructor means that an interval must be provided, via + /// reader.Interval(i), before iterating. + /// + /// \param[in] bamFiles input BamFile objects + /// + /// \throws std::runtime_error if either file (*.bam or *.bai) fails to open + /// for reading, or if the interval is invalid + /// + GenomicIntervalCompositeBamReader(const std::vector& bamFiles); + GenomicIntervalCompositeBamReader(const std::vector& bamFiles, + const BaiIndexCache& cache); + + /// \brief Constructs composite %BAM reader, that can be queried on genomic interval. + /// + /// \note Using this constructor means that an interval must be provided, via + /// reader.Interval(i), before iterating. + /// + /// \param[in] dataset input DataSet + /// + /// \throws std::runtime_error if either file (*.bam or *.bai) fails to open + /// for reading, or if the interval is invalid + /// + GenomicIntervalCompositeBamReader(const DataSet& dataset); + GenomicIntervalCompositeBamReader(const DataSet& dataset, const BaiIndexCache& cache); + + /// \brief Constructs composite %BAM reader, limiting record results to + /// only those overalpping a GenomicInterval. + /// + /// \param[in] interval genomic interval of interest + /// \param[in] bamFiles input BamFile objects + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or + /// BAI files. + /// + GenomicIntervalCompositeBamReader(const GenomicInterval& interval, + const std::vector& bamFiles); + GenomicIntervalCompositeBamReader(const GenomicInterval& interval, + const std::vector& bamFiles, + const BaiIndexCache& cache); + + /// \brief Constructs composite %BAM reader, limiting record results to + /// only those overalpping a GenomicInterval. + /// + /// \param[in] interval genomic interval of interest + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or + /// BAI files. + /// + GenomicIntervalCompositeBamReader(const GenomicInterval& interval, const DataSet& dataset); + GenomicIntervalCompositeBamReader(const GenomicInterval& interval, const DataSet& dataset, + const BaiIndexCache& cache); + + /// \} + +public: + /// \name Data Access + /// \{ + + /// Fetches next BAM record in the interval specified, storing in \p record + /// + /// \param[out] record + /// \returns true on success, false if no more data available. + /// + bool GetNext(BamRecord& record); + + /// Sets a new genomic interval of interest. + /// + /// \returns reference to this reader + /// + GenomicIntervalCompositeBamReader& Interval(const GenomicInterval& interval); + + /// \returns the current specified interval + /// + const GenomicInterval& Interval() const; + + /// \} + +private: + void UpdateSort(); + +private: + BaiIndexCache indexCache_; + GenomicInterval interval_; + std::deque mergeItems_; + std::vector filenames_; +}; + +/// \brief Provides read access to multipe %BAM files, limiting results to those +/// passing a PbiFilter. +/// +/// Requires a ".pbi" file for each input %BAM file. +/// +/// \note The template parameter OrderByType is not fully implemented at this +/// time. Use of comparison functor (e.g. Compare::Zmw) for this will +/// currently result in the proper "next" value at each iteration +/// step, independently, but not over the full data set. If all +/// files' "order-by" data values are accessible in increasing order +/// within each file, then the expected ordering will be observed, +/// However, if these data are not sorted within a file, the final results +/// will appear unordered. \n +/// \n +/// Example:\n +/// file 1: { 1, 5, 2, 6 } \n +/// file 2: { 3, 8, 4, 7 } \n +/// results: { 1, 3, 5, 2, 6, 8, 4, 7 } \n +/// \n +/// This a known issue and will be addressed in a future update. But in +/// the meantime, use of Compare::None as the OrderByType is recommended, +/// to explicitly indicate that no particular ordering is expected. +/// +template +class PBBAM_EXPORT PbiFilterCompositeBamReader +{ +public: + using value_type = internal::CompositeMergeItem; + using merge_sorter_type = internal::CompositeMergeItemSorter; + using container_type = std::deque; + using iterator = typename container_type::iterator; + using const_iterator = typename container_type::const_iterator; + +public: + /// \name Contstructors & Related Methods + /// \{ + + PbiFilterCompositeBamReader(const PbiFilter& filter, const std::vector& bamFiles); + PbiFilterCompositeBamReader(const PbiFilter& filter, const std::vector& bamFiles, + const PbiIndexCache& cache); + + PbiFilterCompositeBamReader(const PbiFilter& filter, const DataSet& dataset); + PbiFilterCompositeBamReader(const PbiFilter& filter, const DataSet& dataset, + const PbiIndexCache& cache); + + /// \} + +public: + /// \name Data Access + /// \{ + + /// Fetches next BAM record in the interval specified. + /// + /// \returns true on success, false if no more data available. + /// + bool GetNext(BamRecord& record); + + /// Sets a new PBI filter + /// + /// \returns reference to this reader + /// + PbiFilterCompositeBamReader& Filter(const PbiFilter& filter); + + uint32_t NumReads() const; + + /// \} + +private: + void UpdateSort(); + +private: + PbiIndexCache indexCache_; + container_type mergeQueue_; + std::vector filenames_; + uint32_t numReads_; +}; + +/// \brief The SequentialCompositeBamReader class provides read access to +/// multiple %BAM files, reading through the entire contents of each +/// file. +/// +/// Input files will be accessed in the order provided to the constructor. Each +/// file's contents will be exhausted before moving on to the next one (as +/// opposed to a "round-robin" scheme). +/// +class PBBAM_EXPORT SequentialCompositeBamReader +{ +public: + /// \name Contstructors & Related Methods + /// \{ + + SequentialCompositeBamReader(std::vector bamFiles); + SequentialCompositeBamReader(const DataSet& dataset); + + /// \} + +public: + /// \name Data Access + /// \{ + + /// Fetches next BAM record from the . + /// + /// \returns true on success, false if no more data available. + /// + bool GetNext(BamRecord& record); + + /// \} + +private: + std::deque > readers_; +}; + +} // namespace BAM +} // namespace PacBio + +#include "pbbam/internal/CompositeBamReader.inl" + +#endif // COMPOSITEBAMREADER_H diff --git a/include/pbbam/CompositeFastaReader.h b/include/pbbam/CompositeFastaReader.h new file mode 100644 index 0000000..cd50f9f --- /dev/null +++ b/include/pbbam/CompositeFastaReader.h @@ -0,0 +1,63 @@ +// File Description +/// \file CompositeFastaReader.h +/// \brief Defines the composite FASTA reader, for working with multiple input +/// files. +// +// Author: Derek Barnett + +#ifndef COMPOSITEFASTAREADER_H +#define COMPOSITEFASTAREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include "pbbam/DataSet.h" +#include "pbbam/FastaReader.h" +#include "pbbam/FastaSequence.h" + +namespace PacBio { +namespace BAM { + +/// \brief The CompositeFastaReader class provides read access to +/// multiple FASTA files, reading through the entire contents of each +/// file. +/// +/// Input files will be accessed in the order provided to the constructor. Each +/// file's contents will be exhausted before moving on to the next one (as +/// opposed to a "round-robin" scheme). +/// +class PBBAM_EXPORT CompositeFastaReader +{ +public: + /// \name Contstructors & Related Methods + /// \{ + + CompositeFastaReader(const std::vector& fastaFiles); + CompositeFastaReader(const DataSet& dataset); + + /// \} + +public: + /// \name Data Access + /// \{ + + /// Fetches next FASTA sequence. + /// + /// \returns true on success, false if no more data available. + /// + bool GetNext(FastaSequence& seq); + + /// \} + +private: + std::deque > readers_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // COMPOSITEFASTAREADER_H diff --git a/include/pbbam/Config.h b/include/pbbam/Config.h new file mode 100644 index 0000000..a314d3e --- /dev/null +++ b/include/pbbam/Config.h @@ -0,0 +1,67 @@ +// File Description +/// \file Config.h +/// \brief Defines library-wide macros & global variables. +// +// Author: Derek Barnett + +#ifndef PBBAM_CONFIG_H +#define PBBAM_CONFIG_H + +/// \name Library Import/Export +/// \{ + +#ifndef PBBAM_EXPORT +#if defined(WIN32) +#define PBBAM_EXPORT __declspec(dllimport) +#else +#define PBBAM_EXPORT +#endif +#endif + +/// \} + +/// \name Switch for warnings for the pbbam -> pbcopper Data:: move +/// \{ + +#ifdef PACBIO_NODEPRECATED_API +#define PBBAM_DEPRECATED [[deprecated("Use the version from pbcopper in Data::")]] +#else +#define PBBAM_DEPRECATED +#endif + +/// \} + +namespace PacBio { +namespace BAM { + +/// \name Verbosity Settings +/// \{ + +/// \brief Sets the desired verbosity level of htslib warnings. +/// +/// Change this value to allow debug/warning statements from htslib itself. +/// The valid range seems to be [0-3], where 0 indicates OFF, and 3 is the +/// most verbose. +/// +/// By default, pbbam disables htslib statements to keep output channels clean. +/// We rely on exceptions & their associated messages instead. +/// +/// This global variable is obviously not thread-safe by any means. But as a +/// debug flag, it is unlikely to cause any real issues. The worst case would be +/// unexpected presence/absence of output statements. +/// +extern int HtslibVerbosity; + +/// +/// \brief DoesHtslibSupportLongCigar +/// +/// \return true if runtime htslib is >= v1.7 +/// +bool DoesHtslibSupportLongCigar(); + +/// \} + +} // namespace BAM +} // namespace PacBio + +#endif // PBBAM_CONFIG_H diff --git a/include/pbbam/DataSet.h b/include/pbbam/DataSet.h new file mode 100644 index 0000000..886cd02 --- /dev/null +++ b/include/pbbam/DataSet.h @@ -0,0 +1,835 @@ +// File Description +/// \file DataSet.h +/// \brief Defines the DataSet class. +// +// Author: Derek Barnett + +#ifndef DATASET_H +#define DATASET_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include "pbbam/BamFile.h" +#include "pbbam/DataSetTypes.h" +#include "pbbam/GenomicInterval.h" + +namespace PacBio { +namespace BAM { + +/// \brief The DataSet class represents a %PacBio analyis dataset (e.g. from +/// XML). +/// +/// \nosubgrouping +/// +/// It provides resource paths, filters, and metadata associated with a dataset +/// under analysis. +/// +class PBBAM_EXPORT DataSet +{ +public: + /// \name DataSet Type + /// \{ + + /// \brief This enum defines the currently-supported DataSet types. + /// + enum TypeEnum + { + GENERIC = 0, + ALIGNMENT, + BARCODE, + CONSENSUS_ALIGNMENT, + CONSENSUS_READ, + CONTIG, + HDF_SUBREAD, + REFERENCE, + SUBREAD, + TRANSCRIPT, + TRANSCRIPT_ALIGNMENT + }; + + /// \brief Converts printable dataset type to type enum. + /// + /// \param[in] typeName printable dataset type + /// \returns dataset type enum + /// \throws std::runtime_error if \p typeName is unknown + /// + static DataSet::TypeEnum NameToType(const std::string& typeName); + + /// \brief Converts dataset type enum to printable name. + /// + /// \param[in] type dataset type enum + /// \returns printable dataset type + /// \throws std::runtime_error if \p type is unknown + /// + static std::string TypeToName(const DataSet::TypeEnum& type); + + /// \} + +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Constructs an empty, generic DataSet. + /// + DataSet(); + + /// \brief Constructs an empty DataSet of the type specified. + /// + /// \param[in] type dataset type + /// \throws std::runtime_error if \p type is unknown + /// + DataSet(const DataSet::TypeEnum type); + + /// \brief Constructs a DataSet from a %BAM file. + /// + /// This currently defaults to a SubreadSet, with an ExternalResource + /// pointing to BamFile::Filename. + /// + /// \param[in] bamFile BamFile object + /// + DataSet(const BamFile& bamFile); + + /// \brief Loads a DataSet from a file. + /// + /// \p filename may be one of the following types, indicated by its extension:\n + /// - %BAM ("*.bam") \n + /// - FOFN ("*.fofn") \n + /// - FASTA ("*.fa" or "*.fasta") \n + /// - DataSetXML ("*.xml") \n + /// + /// \param[in] filename input filename + /// \throws std::runtime_error if \p filename has an unsupported extension, + /// or if a valid DataSet could not be created from its contents + /// + DataSet(const std::string& filename); + + /// \brief Constructs a DataSet from a list of files. + /// + /// \param[in] filenames input filenames + /// \throws std::runtime_error if DataSet could not be created from + /// \p filenames + /// + DataSet(const std::vector& filenames); + + DataSet(const DataSet&); + DataSet(DataSet&&) noexcept = default; + DataSet& operator=(const DataSet&); + DataSet& operator=(DataSet&&) noexcept = default; + + /// \brief Creates a DataSet from "raw" XML data. + /// + /// \param[in] xml DataSetXML text + /// + static DataSet FromXml(const std::string& xml); + + /// \} + +public: + /// \name Operators + /// \{ + + /// \brief Merges DataSet contents. + /// + /// Adds contents of \p other to this dataset object + /// + /// \param[in] other some other dataset to add to this one + /// \returns reference to this dataset object + /// + DataSet& operator+=(const DataSet& other); + + /// \} + +public: + /// \name Serialization + /// \{ + + /// \brief Saves dataset XML to file. + /// + /// \param[in] outputFilename destination for XML contents + /// + /// \throws std::runtime_error if file could be opened or if DataSet + /// elements could not be converted to XML + /// + void Save(const std::string& outputFilename) const; + + /// \brief Saves dataset XML to output stream, e.g. std::cout, + /// std::stringstream. + /// + /// \param[out] out destination for XML contents + /// + /// \throws std::runtime_error if DataSet elements could not be converted to + /// XML + /// + void SaveToStream(std::ostream& out) const; + + /// \} + +public: + /// \name Attributes + /// \{ + /// + + /// \brief Fetches the value of a DataSet root element's attribute. + /// + /// These are the attributes attached to the root dataset element: \n + /// \verbatim \endverbatim + /// + /// Built-in accessors exist for the standard attributes (e.g. CreatedAt) + /// but additional attributes can be used as well via these generic + /// Attribute methods. + /// + /// \param[in] name root element's attribute name + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& Attribute(const std::string& name) const; + + /// \brief Fetches the value of dataset's CreatedAt attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& CreatedAt() const; + + /// \brief Fetches the value of dataset's Format attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& Format() const; + + /// \brief Fetches the value of dataset's MetaType attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& MetaType() const; + + /// \brief Fetches the value of dataset's ModifiedAt attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& ModifiedAt() const; + + /// \brief Fetches the value of dataset's Name attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& Name() const; + + /// \brief Fetches the value of dataset's ResourceId attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& ResourceId() const; + + /// \brief Fetches the value of dataset's Tags attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& Tags() const; + + /// \brief Fetches the value of dataset's TimeStampedName attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& TimeStampedName() const; + + /// \brief Fetches the value of dataset's UniqueId attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& UniqueId() const; + + /// \brief Fetches the value of dataset's Version attribute. + /// + /// \returns const reference to attribute's value (empty string if not + /// present) + /// + const std::string& Version() const; + + /// \} + +public: + /// \name DataSet Type + /// \{ + + /// \brief Fetches the dataset's type. + /// + /// \returns dataset type enum + /// + PacBio::BAM::DataSet::TypeEnum Type() const; + + /// \brief Fetches the dataset's type. + /// + /// \returns printable dataset type + /// + std::string TypeName() const; + + /// \} + +public: + /// \name Child Elements + /// \{ + + /// \brief Fetches the dataset's Extensions element. + /// + /// \returns const reference to child element + /// \throws std::runtime_error if element does not exist + /// + const PacBio::BAM::Extensions& Extensions() const; + + /// \brief Fetches the dataset's ExternalResources element. + /// + /// \returns const reference to child element + /// \throws std::runtime_error if element does not exist + /// + const PacBio::BAM::ExternalResources& ExternalResources() const; + + /// \brief Fetches the dataset's Filters element. + /// + /// \returns const reference to child element + /// + const PacBio::BAM::Filters& Filters() const; + + /// \brief Fetches the dataset's DataSetMetadata element. + /// + /// \returns const reference to child element + /// + const PacBio::BAM::DataSetMetadata& Metadata() const; + + /// \brief Fetches the dataset's DataSets element. + /// + /// \returns const reference to child element + /// + const PacBio::BAM::SubDataSets& SubDataSets() const; + + /// \} + +public: + /// \name Resource Handling + /// \{ + + /// \brief Returns all of this dataset's resource files, with relative + /// filepaths already resolved. + /// + /// Includes both primary resources (e.g. subread BAM files), as well as all + /// secondary or child resources (e.g. index files, scraps BAM, etc). + /// + /// \returns vector of (resolveD) filepaths + /// + /// \sa DataSet::ResolvedResourceIds + /// + std::vector AllFiles() const; + + /// \brief Returns this dataset's primary %BAM resources, with relative + /// filepaths already resolved. + /// + /// Primary resources are those listed as top-level %ExternalResources, not + /// associated files (indices, references, scraps %BAMs, etc.). + /// + /// \returns vector of BamFiles + /// + /// \sa DataSet::ResolvedResourceIds + /// + std::vector BamFiles() const; + + /// \brief Returns all filenames for BamFiles(), with paths resolved. + /// + // Unlike BamFiles(), this does not actually open the BAM files. + // (BamFile(fn) would read the header.) + // + /// \returns vector of std::string + /// + /// \sa DataSet::BamFiles + /// + std::vector BamFilenames() const; + + /// \brief Returns this dataset's primary FASTA resources, with relative + /// filepaths already resolved. + /// + /// Primary resources are those listed as top-level %ExternalResources, not + /// associated files (indices, references, scraps %BAMs, etc.). + /// + /// \returns vector of filepaths to FASTA resources + /// + /// \sa DataSet::ResolvedResourceIds + /// + std::vector FastaFiles() const; + + /// + /// \returns (absolute) path for dataset + /// + const std::string& Path() const; + + /// \brief Returns all primary external resource filepaths, with relative + /// paths resolved. + /// + /// Primary resources are those listed as top-level %ExternalResources, not + /// associated files (indices, references, scraps %BAMs, etc.). + /// + /// \sa ResolvePath + /// + /// \returns resourceIds + /// + std::vector ResolvedResourceIds() const; + + /// \brief Resolves a filepath (that may be relative to the dataset). + /// + /// A DataSet's resources may be described using absolute filepaths or with + /// relative paths. For absolute paths, nothing is changed from the input. + /// For relative paths, these are resolved using the DataSet's own path + /// as a starting point. A DataSet's own path will be one of:\n + /// 1 - the location of its XML or %BAM input file, e.g. created using + /// DataSet("foo.xml") or DataSet("foo.bam")\n + /// 2 - application's current working directory for all other DataSet + /// construction methods { DataSet(), DataSet(type), + /// DataSet("foo.fofn") }\n + /// + /// \param[in] originalPath input file path (absolute or relative) + /// \returns resolved path + /// + std::string ResolvePath(const std::string& originalPath) const; + + /// \returns sequence chemistry info for all read groups in this dataset + /// + /// \sa ReadGroupInfo::SequencingChemistry + /// + std::set SequencingChemistries() const; + + /// \brief Return a minimal list of genomic intervals covered by filters. + /// + /// \returns vector of genomic intervals + /// + /// \throws std::runtime_error if DataSet contains invalid or non-sensical + /// filters, such as rname appearing twice, etc. + /// + std::vector GenomicIntervals() const; + + /// \} + +public: + /// \name XML Namespace Handling + /// \{ + + /// \brief Access this dataset's namespace info. + /// + /// \returns const reference to dataset's NamespaceRegistry + /// + const NamespaceRegistry& Namespaces() const; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// \brief Fetches the value of a DataSet root element's attribute. + /// + /// These are the attributes attached to the root dataset element: \n + /// \verbatim \endverbatim + /// + /// Built-in accessors exist for the standard attributes (e.g. CreatedAt) + /// but additional attributes can be used as well via these generic methods. + /// + /// A new attribute will be created if it does not yet exist. + /// + /// \param[in] name root element's attribute name + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& Attribute(const std::string& name); + + /// \brief Fetches the value of dataset's CreatedAt attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& CreatedAt(); + + /// \brief Fetches the value of dataset's Format attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& Format(); + + /// \brief Fetches the value of dataset's MetaType attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& MetaType(); + + /// \brief Fetches the value of dataset's ModifiedAt attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& ModifiedAt(); + + /// \brief Fetches the value of dataset's Name attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& Name(); + + /// \brief Fetches the value of dataset's ResourceId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& ResourceId(); + + /// \brief Fetches the value of dataset's Tags attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& Tags(); + + /// \brief Fetches the value of dataset's TimeStampedName attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& TimeStampedName(); + + /// \brief Fetches the value of dataset's UniqueId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& UniqueId(); + + /// \brief Fetches the value of dataset's Version attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute's value (empty string if this + /// is a new attribute) + /// + std::string& Version(); + + /// \} + +public: + /// \name Attributes + /// \{ + + /// \brief Sets this dataset's XML attribute \p name, with \p value + /// + /// These are the attributes attached to the root dataset element: \n + /// \verbatim \endverbatim + /// + /// Built-in accessors exist for the standard attributes (e.g. CreatedAt) + /// but additional attributes can be used as well via these generic methods. + /// + /// The attribute will be created if it does not yet exist. + /// + /// \param[in] name root element's attribute name + /// \param[in] value new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& Attribute(const std::string& name, const std::string& value); + + /// \brief Sets this dataset's CreatedAt attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] createdAt new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& CreatedAt(const std::string& createdAt); + + /// \brief Sets this dataset's Format attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] format new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& Format(const std::string& format); + + /// \brief Sets this dataset's MetaType attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] metatype new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& MetaType(const std::string& metatype); + + /// \brief Sets this dataset's ModifiedAt attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] modifiedAt new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& ModifiedAt(const std::string& modifiedAt); + + /// \brief Sets this dataset's Name attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] name new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& Name(const std::string& name); + + /// \brief Sets this dataset's ResourceId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] resourceId new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& ResourceId(const std::string& resourceId); + + /// \brief Sets this dataset's Tags attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] tags new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& Tags(const std::string& tags); + + /// \brief Sets this dataset's TimeStampedName attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] timeStampedName new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& TimeStampedName(const std::string& timeStampedName); + + /// \brief Sets this dataset's UniqueId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] uuid new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& UniqueId(const std::string& uuid); + + /// \brief Sets this dataset's Version attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] version new value for the attribute + /// \returns reference to this dataset object + /// + DataSet& Version(const std::string& version); + + /// \} + +public: + /// \name DataSet Type + /// \{ + + /// \brief Edits dataset type. + /// + /// \param[in] type new dataset type + /// \returns reference to this dataset object + /// + DataSet& Type(const PacBio::BAM::DataSet::TypeEnum type); + + /// \} + +public: + /// \name Child Elements + /// \{ + + /// \brief Fetches the dataset's Extensions element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::Extensions& Extensions(); + + /// \brief Fetches the dataset's ExternalResources element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::ExternalResources& ExternalResources(); + + /// \brief Fetches the dataset's Filters element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::Filters& Filters(); + + /// \brief Fetches the dataset's DataSetMetadata element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::DataSetMetadata& Metadata(); + + /// \brief Fetches the dataset's DataSets element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::SubDataSets& SubDataSets(); + + /// \} + +public: + /// \name Child Elements + /// \{ + + /// \brief Sets this dataset's Extensions element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] extensions new value for the element + /// \returns reference to this dataset object + /// + DataSet& Extensions(const PacBio::BAM::Extensions& extensions); + + /// \brief Sets this dataset's ExternalResources element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] resources new value for the element + /// \returns reference to this dataset object + /// + DataSet& ExternalResources(const PacBio::BAM::ExternalResources& resources); + + /// \brief Sets this dataset's Filters element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] filters new value for the element + /// \returns reference to this dataset object + /// + DataSet& Filters(const PacBio::BAM::Filters& filters); + + /// \brief Sets this dataset's DataSetMetadata element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] metadata new value for the element + /// \returns reference to this dataset object + /// + DataSet& Metadata(const PacBio::BAM::DataSetMetadata& metadata); + + /// \brief Sets this dataset's DataSets element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] subdatasets new value for the element + /// \returns reference to this dataset object + /// + DataSet& SubDataSets(const PacBio::BAM::SubDataSets& subdatasets); + + /// \} + +public: + /// \name XML Namespace Handling + /// \{ + + /// \brief Access this dataset's namespace info. + /// + /// \returns non-const reference to dataset's NamespaceRegistry + /// + NamespaceRegistry& Namespaces(); + + /// \} + +private: + std::unique_ptr d_; +}; + +/// \name DataSet Timestamp Utilities +/// \{ + +/// \brief Fetches current time, in "DataSetXML format". +/// +/// \returns DataSetXML formatted timestamp +/// +/// \sa ToDataSetFormat +/// +PBBAM_EXPORT std::string CurrentTimestamp(); + +/// \brief Converts a time_point to "DataSetXML-formatted" timestamp. +/// +/// This is the format used as a component of the DataSet::TimeStampedName +/// (yymmdd_HHmmssttt>. +/// +/// \returns "DataSetXML-formatted" timestamp +/// +PBBAM_EXPORT std::string ToDataSetFormat(const std::chrono::system_clock::time_point& tp); + +/// \brief Converts a time_t to "DataSetXML-formatted" timestamp. +/// +/// This is the format used as a component of the DataSet::TimeStampedName +/// (yymmdd_HHmmssttt>. +/// +/// \returns "DataSetXML-formatted" timestamp +/// +PBBAM_EXPORT std::string ToDataSetFormat(const time_t& tp); + +/// \brief Converts a time_point to ISO-8601 formatted timestamp. +/// +/// This is the format used in DataSet::CreatedAt and DataSet::ModifiedAt. +/// +/// \returns ISO-8601 formatted timestamp +/// +PBBAM_EXPORT std::string ToIso8601(const std::chrono::system_clock::time_point& tp); + +/// \brief Converts a time_t to ISO-8601 formatted timestamp. +/// +/// This is the format used in DataSet::CreatedAt and DataSet::ModifiedAt. +/// +/// \returns ISO-8601 formatted timestamp +/// +PBBAM_EXPORT std::string ToIso8601(const time_t& t); + +/// \} + +} // namespace BAM +} // namespace PacBio + +#endif // DATASET_H diff --git a/include/pbbam/DataSetTypes.h b/include/pbbam/DataSetTypes.h new file mode 100644 index 0000000..4bab41d --- /dev/null +++ b/include/pbbam/DataSetTypes.h @@ -0,0 +1,1211 @@ +// File Description +/// \file DataSetTypes.h +/// \brief Defines the public DataSet component classes. +// +// Author: Derek Barnett + +#ifndef DATASETTYPES_H +#define DATASETTYPES_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/BamFile.h" +#include "pbbam/DataSetXsd.h" +#include "pbbam/internal/DataSetBaseTypes.h" + +namespace PacBio { +namespace BAM { + +/// +/// \brief The DNABarcode class represents a %DNABarcode element in +/// DataSetXML, consisting of a Name and optional UniqueId. +/// +class PBBAM_EXPORT DNABarcode : public internal::DataSetElement +{ +public: + DNABarcode(const std::string& name); + DNABarcode(const std::string& name, const std::string& uuid); + DNABarcode(const std::string& name, const internal::FromInputXml& fromInputXml); + DNABarcode(const std::string& name, const std::string& uuid, + const internal::FromInputXml& fromInputXml); + + const std::string& Name() const; + std::string& Name(); + DNABarcode& Name(const std::string& name); + + const std::string& UniqueId() const; + std::string& UniqueId(); + DNABarcode& UniqueId(const std::string& name); +}; + +/// \brief The DNABarcodes class represents an %DNABarcodes element in DataSetXML. +/// +/// The DNABarcodes element is essentially just a list of DNABarcode +/// objects. +/// +class PBBAM_EXPORT DNABarcodes : public internal::DataSetElement +{ +public: + DNABarcodes(); + DNABarcodes(const internal::FromInputXml& fromInputXml); + +public: + void Add(const DNABarcode& barcode); + void Remove(const DNABarcode& barcode); + +public: + using value_type = DNABarcode; + using iterator_type = internal::DataSetElementIterator; + using const_iterator_type = internal::DataSetElementConstIterator; + + const value_type& operator[](size_t index) const; + value_type& operator[](size_t index); + + iterator_type begin(); + const_iterator_type begin() const; + const_iterator_type cbegin() const; + iterator_type end(); + const_iterator_type end() const; + const_iterator_type cend() const; +}; + +class PBBAM_EXPORT BioSample : public internal::DataSetElement +{ +public: + BioSample(const std::string& name); + BioSample(const std::string& name, const internal::FromInputXml& fromInputXml); + + const PacBio::BAM::DNABarcodes& DNABarcodes() const; + PacBio::BAM::DNABarcodes& DNABarcodes(); + BioSample& DNABarcodes(const PacBio::BAM::DNABarcodes& barcodes); + + const std::string& Name() const; + std::string& Name(); + BioSample& Name(const std::string& name); +}; + +/// \brief The DNABarcodes class represents an %DNABarcodes element in DataSetXML. +/// +/// The DNABarcodes element is essentially just a list of DNABarcode +/// objects. +/// +class PBBAM_EXPORT BioSamples : public internal::DataSetElement +{ +public: + BioSamples(); + BioSamples(const internal::FromInputXml& fromInputXml); + +public: + void Add(const BioSample& sample); + void Remove(const BioSample& sample); + +public: + using value_type = BioSample; + using iterator_type = internal::DataSetElementIterator; + using const_iterator_type = internal::DataSetElementConstIterator; + + const value_type& operator[](size_t index) const; + value_type& operator[](size_t index); + + iterator_type begin(); + const_iterator_type begin() const; + const_iterator_type cbegin() const; + iterator_type end(); + const_iterator_type end() const; + const_iterator_type cend() const; +}; + +/// \brief The ExtensionElement class represents an %ExtensionElement element in +/// DataSetXML. +/// +class PBBAM_EXPORT ExtensionElement : public internal::DataSetElement +{ +public: + ExtensionElement(); + ExtensionElement(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The Extensions class represents an %Extensions element in DataSetXML. +/// +/// The Extensions element is essentially just a list of ExtensionElement +/// objects. +/// +class PBBAM_EXPORT Extensions : public internal::DataSetElement +{ +public: + /// \brief Creates an empty extensions list. + Extensions(); + Extensions(const internal::FromInputXml& fromInputXml); + +public: + using value_type = ExtensionElement; + using iterator_type = internal::DataSetElementIterator; + using const_iterator_type = internal::DataSetElementConstIterator; + + const value_type& operator[](size_t index) const; + value_type& operator[](size_t index); + + iterator_type begin(); + const_iterator_type begin() const; + const_iterator_type cbegin() const; + iterator_type end(); + const_iterator_type end() const; + const_iterator_type cend() const; +}; + +class ExternalResources; + +/// \brief The ExternalResource class represents an %ExternalResource element in +/// DataSetXML. +/// +/// An ExternalResource can itself have a child element, ExternalResources, that +/// lists related files (e.g. index files). +/// +class PBBAM_EXPORT ExternalResource : public internal::IndexedDataType +{ +public: + /// \brief Creates an ExternalResource from a BamFile object. + /// + /// The metatype & resourceId are automatically set. + /// + ExternalResource(const BamFile& bamFile); + + /// \brief Creates an ExternalResource with provided \p metatype and + /// \p filename as resource ID. + /// + ExternalResource(const std::string& metatype, const std::string& filename); + + ExternalResource(const std::string& metatype, const std::string& filename, + const internal::FromInputXml& fromInputXml); + +public: + /// \brief Fetches the resource's ExternalResources child element. + /// + /// \returns const reference to child element + /// \throws std::runtime_error if element does not exist + /// + const PacBio::BAM::ExternalResources& ExternalResources() const; + +public: + /// \brief Fetches the resource's ExternalResources child element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::ExternalResources& ExternalResources(); + + /// \brief Sets this resource's ExternalResources child element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] resources new value for the element + /// \returns reference to this resource object + /// + ExternalResource& ExternalResources(const PacBio::BAM::ExternalResources& resources); + +public: + /// \brief Converts an ExternalResource to a BamFile object + /// + /// \returns corresponding BamFile object for this ExternalResource + /// \throws std::runtime_error if fails to open %BAM file (e.g. does not + /// exist, not a %BAM file, etc.) + /// + /// \deprecated Use the results from DataSet::BamFiles instead. This method + /// cannot resolve relative filepaths and will be removed in the + /// near future. + /// + BamFile ToBamFile() const; +}; + +/// \brief The ExternalResources class represents an %ExternalResources element +/// in DataSetXML. +/// +/// The ExternalResources element is essentially just a list of ExternalResource +/// elements. +/// +class PBBAM_EXPORT ExternalResources : public internal::DataSetElement +{ +public: + /// \brief Creates an empty resource list. + ExternalResources(); + ExternalResources(const internal::FromInputXml& fromInputXml); + + /// \brief Merges \p other resource list with this one. + ExternalResources& operator+=(const ExternalResources& other); + +public: + /// \brief Adds an ExternalResource to this list. + void Add(const ExternalResource& ext); + + /// \brief Removes an ExternalResource from this list. + void Remove(const ExternalResource& ext); + +public: + /// \brief Converts resource list to BamFile objects. + /// + /// \deprecated Use DataSet::BamFiles instead. This method cannot resolve + /// relative filepaths and will be removed in the near future. + /// + std::vector BamFiles() const; + +public: + using value_type = ExternalResource; + using iterator_type = internal::DataSetElementIterator; + using const_iterator_type = internal::DataSetElementConstIterator; + + const value_type& operator[](size_t index) const; + value_type& operator[](size_t index); + + iterator_type begin(); + const_iterator_type begin() const; + const_iterator_type cbegin() const; + iterator_type end(); + const_iterator_type end() const; + const_iterator_type cend() const; +}; + +/// \brief The FileIndex class represents a %FileIndex element in DataSetXML. +/// +/// A FileIndex is used as an auxiliary to an ExternalResource, providing +/// information about a data file's index file (e.g. for %BAM files, *.bai or +/// *.pbi). +/// +class PBBAM_EXPORT FileIndex : public internal::InputOutputDataType +{ +public: + /// \brief Creates a FileIndex with provided \p metatype and \p filename as + /// resource ID. + /// + FileIndex(const std::string& metatype, const std::string& filename); + + FileIndex(const std::string& metatype, const std::string& filename, + const internal::FromInputXml& fromInputXml); +}; + +/// \brief The FileIndices class represents a %FileIndices element in DataSetXML. +/// +/// The FileIndices element is essentially just a list of FileIndex elements, +/// providing information about a data file's index files (e.g. for %BAM files +/// this will usually be *.bai and/or *.pbi). +/// +class PBBAM_EXPORT FileIndices : public internal::DataSetElement +{ +public: + /// \brief Creates an empty index list. + FileIndices(); + FileIndices(const internal::FromInputXml& fromInputXml); + +public: + /// \brief Adds a FileIndex to this list. + void Add(const FileIndex& index); + + /// \brief Removes a FileIndex from this list. + void Remove(const FileIndex& index); + +public: + using value_type = FileIndex; + using iterator_type = internal::DataSetElementIterator; + using const_iterator_type = internal::DataSetElementConstIterator; + + const value_type& operator[](size_t index) const; + value_type& operator[](size_t index); + + iterator_type begin(); + const_iterator_type begin() const; + const_iterator_type cbegin() const; + iterator_type end(); + const_iterator_type end() const; + const_iterator_type cend() const; +}; + +/// \brief The Filter class represents a %Filter element in DataSetXML. +/// +/// The Filter element allows analysis pipelines to describe filters on data +/// that should be respected downstream, without needing to create filtered +/// intermediate files. +/// +/// A filter consists of a list of Property elements, each of which must be +/// passed (logical AND) to pass the filter, e.g. property1 && property2 && +/// property3. +/// +class PBBAM_EXPORT Filter : public internal::DataSetElement +{ +public: + /// \brief Creates an empty filter. + Filter(); + Filter(const internal::FromInputXml& fromInputXml); + +public: + /// \brief Fetches the filter's property list element. + /// + /// \returns const reference to child element + /// \throws std::runtime_error if element does not exist + /// + const PacBio::BAM::Properties& Properties() const; + +public: + /// \brief Fetches the filter's property list child element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::Properties& Properties(); + + /// \brief Sets this filter's Properties child element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] properties new value for the element + /// \returns reference to this filter object + /// + Filter& Properties(const PacBio::BAM::Properties& properties); +}; + +/// \brief The Filters class represents a %Filters list element in DataSetXML. +/// +/// The Filters element is essentially a list of Filter elements. For analysis +/// purpose, each filter is considered separately (logical OR) to consider which +/// data passes, e.g. filter1 || filter2 || filter3. +/// +class PBBAM_EXPORT Filters : public internal::DataSetElement +{ +public: + /// \brief Creates an empty filter list. + Filters(); + Filters(const internal::FromInputXml& fromInputXml); + + /// \brief Merges \p other filter list with this one. + Filters& operator+=(const Filters& other); + +public: + /// \brief Adds a filter to this list. + void Add(const Filter& filter); + + /// \brief Removes a filter from this list. + void Remove(const Filter& filter); + +public: + using value_type = Filter; + using iterator_type = internal::DataSetElementIterator; + using const_iterator_type = internal::DataSetElementConstIterator; + + const value_type& operator[](size_t index) const; + value_type& operator[](size_t index); + + iterator_type begin(); + const_iterator_type begin() const; + const_iterator_type cbegin() const; + iterator_type end(); + const_iterator_type end() const; + const_iterator_type cend() const; +}; + +/// \brief The ParentTool class represents a %ParentTool element in DataSetXML. +/// +class PBBAM_EXPORT ParentTool : public internal::BaseEntityType +{ +public: + /// \brief Creates an empty %ParentTool element. + ParentTool(); + ParentTool(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The Property class represents a %Property element in DataSetXML. +/// +/// A Property is the primary building block of %DataSetXML filtering. The +/// %Property element describes a data record's property (or field), some value, +/// and a comparison operator. +/// +/// For example, one could filter all %BAM records with a read accuracy at or +/// above 0.9. In C++ this could be constructed like: +/// \code{.cpp} +/// Property p("accuracy", "0.9", ">="); +/// \endcode +/// +class PBBAM_EXPORT Property : public internal::DataSetElement +{ +public: + /// \brief Constructs a filter property. + Property(const std::string& name, const std::string& value, const std::string& op); + Property(const std::string& name, const std::string& value, const std::string& op, + const internal::FromInputXml& fromInputXml); + +public: + /// \brief Fetches the value of property's Name attribute. + /// + /// \returns const reference to attribute value + /// + const std::string& Name() const; + + /// \brief Fetches the value of property's Operator attribute. + /// + /// \returns const reference to attribute value + /// + const std::string& Operator() const; + + /// \brief Fetches the value of property's Value attribute. + /// + /// \returns const reference to attribute value + /// + const std::string& Value() const; + +public: + /// \brief Fetches the value of property's Name attribute. + /// + /// \returns non-const reference to attribute value + /// + std::string& Name(); + + /// \brief Fetches the value of property's Operator attribute. + /// + /// \returns non-const reference to attribute value + /// + std::string& Operator(); + + /// \brief Fetches the value of property's Value attribute. + /// + /// \returns nonconst reference to attribute value + /// + std::string& Value(); + +public: + /// \brief Sets this property's Name attribute. + /// + /// \param[in] name new value for the attribute + /// \returns reference to this property object + /// + Property& Name(const std::string& name); + + /// \brief Sets this property's Operator attribute. + /// + /// \param[in] op new value for the attribute + /// \returns reference to this property object + /// + Property& Operator(const std::string& op); + + /// \brief Sets this property's Value attribute. + /// + /// \param[in] value new value for the attribute + /// \returns reference to this property object + /// + Property& Value(const std::string& value); +}; + +/// \brief The Properties class represents a %Properties list element in +/// DataSetXML. +/// +/// The Properties element is essentially a list of Property elements. +/// +class PBBAM_EXPORT Properties : public internal::DataSetElement +{ +public: + /// \brief Creates an empty property list. + Properties(); + Properties(const internal::FromInputXml& fromInputXml); + +public: + /// \brief Adds a property to this list. + void Add(const Property& property); + + /// \brief Removes a property from this list. + void Remove(const Property& property); + +public: + using value_type = Property; + using iterator_type = internal::DataSetElementIterator; + using const_iterator_type = internal::DataSetElementConstIterator; + + const value_type& operator[](size_t index) const; + value_type& operator[](size_t index); + + iterator_type begin(); + const_iterator_type begin() const; + const_iterator_type cbegin() const; + iterator_type end(); + const_iterator_type end() const; + const_iterator_type cend() const; +}; + +/// \brief The Provenance class represents a %Provenance element in DataSetXML. +/// +class PBBAM_EXPORT Provenance : public internal::DataSetElement +{ +public: + /// \brief Creates a empty provenance element. + Provenance(); + Provenance(const internal::FromInputXml& fromInputXml); + +public: + /// \brief Fetches the value of CreatedBy attribute. + /// + /// \returns const reference to attribute value (empty string if not + /// present) + /// + const std::string& CreatedBy() const; + + /// \brief Fetches the value of CommonServicesInstanceId attribute. + /// + /// \returns const reference to attribute value (empty string if not + /// present) + /// + const std::string& CommonServicesInstanceId() const; + + /// \brief Fetches the value of CreatorUserId attribute. + /// + /// \returns const reference to attribute value (empty string if not + /// present) + /// + const std::string& CreatorUserId() const; + + /// \brief Fetches the value of ParentJobId attribute. + /// + /// \returns const reference to attribute value (empty string if not + /// present) + /// + const std::string& ParentJobId() const; + + /// \brief Fetches the ParentTool child element. + /// + /// \returns const reference to child element + /// \throws std::runtime_error if element does not exist + /// + const PacBio::BAM::ParentTool& ParentTool() const; + +public: + /// \brief Fetches the value of CreatedBy attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute value (empty string if this is + /// a new attribute) + /// + std::string& CreatedBy(); + + /// \brief Fetches the value of CommonServicesInstanceId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute value (empty string if this is + /// a new attribute) + /// + std::string& CommonServicesInstanceId(); + + /// \brief Fetches the value of CreatorUserId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute value (empty string if this is + /// a new attribute) + /// + std::string& CreatorUserId(); + + /// \brief Fetches the value of ParentJobId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \returns non-const reference to attribute value (empty string if this is + /// a new attribute) + /// + std::string& ParentJobId(); + + /// \brief Fetches the ParentTool element element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::ParentTool& ParentTool(); + +public: + /// \brief Sets the CreatedBy attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] createdBy new value for the attribute + /// \returns reference to this object + /// + Provenance& CreatedBy(const std::string& createdBy); + + /// \brief Sets the CommonServicesInstanceId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] id new value for the attribute + /// \returns reference to this object + /// + Provenance& CommonServicesInstanceId(const std::string& id); + + /// \brief Sets the CreatorUserId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] id new value for the attribute + /// \returns reference to this object + /// + Provenance& CreatorUserId(const std::string& id); + + /// \brief Sets the ParentJobId attribute. + /// + /// This attribute will be created if it does not yet exist. + /// + /// \param[in] id new value for the attribute + /// \returns reference to this object + /// + Provenance& ParentJobId(const std::string& id); + + /// \brief Sets the ParentTool child element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] tool new value for the element + /// \returns reference to this dataset object + /// + Provenance& ParentTool(const PacBio::BAM::ParentTool& tool); +}; + +/// \brief The DataSetMetadata class represents the %DataSetMetadata child +/// element in DataSetXML. +/// +/// A few top-level elements are built-in, but as pbbam is not primarily a +/// DataSetXML API, most of the metadata hierarchy needs to be manually managed. +/// +class PBBAM_EXPORT DataSetMetadata : public internal::DataSetElement +{ +public: + /// \name Constructors & Related Methods + /// \{ + + DataSetMetadata(); + DataSetMetadata(const internal::FromInputXml& fromInputXml); + + /// \brief Constructs a DataSetMetadata with required fields. + DataSetMetadata(const std::string& numRecords, const std::string& totalLength); + DataSetMetadata(const std::string& numRecords, const std::string& totalLength, + const internal::FromInputXml& fromInputXml); + + /// \} + +public: + /// \name Operators + /// \{ + + /// \brief Merges DataSetMetadata contents. + /// + /// Adds contents of \p other to this metadata object + /// + /// \param[in] other some other metadata to add to this one + /// \returns reference to this object + /// + DataSetMetadata& operator+=(const DataSetMetadata& other); + + /// \} + +public: + /// \name Child Elements + /// \{ + + /// \brief Fetches the text of the NumRecords element. + /// + /// \returns const reference to element text (empty string if not present) + /// + const std::string& NumRecords() const; + + /// \brief Fetches the text of the TotalLength element. + /// + /// \returns const reference to element text (empty string if not present) + /// + const std::string& TotalLength() const; + + /// \brief Fetches the Provenance element. + /// + /// \returns const reference to child element + /// \throws std::runtime_error if element does not exist + /// + const PacBio::BAM::Provenance& Provenance() const; + + /// \brief Fetches the BioSamples element. + /// + /// \returns const reference to child element + /// \throws std::runtime_error if element does not exist + /// + const PacBio::BAM::BioSamples& BioSamples() const; + + /// \} + +public: + /// \name Child Elements + /// \{ + + /// \brief Fetches the text of the NumRecords element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to element text + /// + std::string& NumRecords(); + + /// \brief Fetches the text of the TotalLength element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to element text + /// + std::string& TotalLength(); + + /// \brief Fetches Provenance element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::Provenance& Provenance(); + + /// \brief Fetches BioSamples element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::BioSamples& BioSamples(); + + /// \} + +public: + /// \name Child Elements + /// \{ + + /// \brief Sets the text of the NumRecords element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns reference to this metadata object + /// + DataSetMetadata& NumRecords(const std::string& numRecords); + + /// \brief Sets the text of the TotalLength element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns reference to this metadata object + /// + DataSetMetadata& TotalLength(const std::string& totalLength); + + /// \brief Sets the Provenance child element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns reference to this metadata object + /// + DataSetMetadata& Provenance(const PacBio::BAM::Provenance& provenance); + + /// \brief Sets the BioSamples child element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns reference to this metadata object + /// + DataSetMetadata& BioSamples(const PacBio::BAM::BioSamples& samples); + + /// \} +}; + +class SubDataSets; + +/// \brief The DataSetBase class provides the attributes & child elements shared +/// by all dataset types. +/// +/// Client code should not need to use this class directly. It should be +/// considered as more of an implementation detail and may in fact be removed +/// from public API in the future. The top-level DataSet is the recommended +/// entry point. +/// +class PBBAM_EXPORT DataSetBase : public internal::StrictEntityType +{ +public: + /// \brief Creates a DataSetBase object, or one of its subclasses, from an + /// XML element name (e.g. SubreadSet) + /// + static std::shared_ptr Create(const std::string& typeName); + static std::shared_ptr Create(const std::string& typeName, + const internal::FromInputXml& fromInputXml); + +public: + /// \brief Creates an empty, generic DataSetBase. + DataSetBase(); + DataSetBase(const internal::FromInputXml& fromInputXml); + +protected: + /// \brief Creates a DataSetBase with key values initialized. + DataSetBase(const std::string& metatype, const std::string& label, const XsdType& xsd); + DataSetBase(const std::string& metatype, const std::string& label, + const internal::FromInputXml& fromInputXml, const XsdType& xsd); + + /// \brief Returns a new DataSetBase containing a deep copy of contents + DataSetBase* DeepCopy() const; + +public: + /// \brief Merges dataset contents. + /// + /// Adds contents of \p other to this dataset object + /// + /// \param[in] other some other dataset to add to this one + /// \returns reference to this dataset object + /// + DataSetBase& operator+=(const DataSetBase& other); + +public: + /// \brief Fetches the dataset's ExternalResources element. + /// + /// \returns const reference to child element + /// \throws std::runtime_error if element does not exist + /// + const PacBio::BAM::ExternalResources& ExternalResources() const; + + /// \brief Fetches the dataset's Filters element. + /// + /// \returns const reference to child element + /// + const PacBio::BAM::Filters& Filters() const; + + /// \brief Fetches the dataset's DataSetMetadata element. + /// + /// \returns const reference to child element + /// + const PacBio::BAM::DataSetMetadata& Metadata() const; + + /// \brief Fetches the dataset's DataSets element. + /// + /// \returns const reference to child element + /// + const PacBio::BAM::SubDataSets& SubDataSets() const; + +public: + /// \brief Access this dataset's namespace info. + /// + /// \returns const reference to dataset's NamespaceRegistry + /// + const NamespaceRegistry& Namespaces() const; + +public: + /// \brief Fetches the dataset's ExternalResources element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::ExternalResources& ExternalResources(); + + /// \brief Fetches the dataset's Filters element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::Filters& Filters(); + + /// \brief Fetches the dataset's DataSetMetadata element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::DataSetMetadata& Metadata(); + + /// \brief Fetches the dataset's DataSets element. + /// + /// This element will be created if it does not yet exist. + /// + /// \returns non-const reference to child element + /// + PacBio::BAM::SubDataSets& SubDataSets(); + +public: + /// \brief Sets this dataset's ExternalResources element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] resources new value for the element + /// \returns reference to this dataset object + /// + DataSetBase& ExternalResources(const PacBio::BAM::ExternalResources& resources); + + /// \brief Sets this dataset's Filters element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] filters new value for the element + /// \returns reference to this dataset object + /// + DataSetBase& Filters(const PacBio::BAM::Filters& filters); + + /// \brief Sets this dataset's DataSetMetadata element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] metadata new value for the element + /// \returns reference to this dataset object + /// + DataSetBase& Metadata(const PacBio::BAM::DataSetMetadata& metadata); + + /// \brief Sets this dataset's DataSets element. + /// + /// This element will be created if it does not yet exist. + /// + /// \param[in] subdatasets new value for the element + /// \returns reference to this dataset object + /// + DataSetBase& SubDataSets(const PacBio::BAM::SubDataSets& subdatasets); + +public: + /// \brief Access this dataset's namespace info. + /// + /// \returns non-const reference to dataset's NamespaceRegistry + /// + NamespaceRegistry& Namespaces(); + +public: + /// \brief Saves dataset XML to file. + /// + /// \param[in] outputFilename destination for XML contents + /// + /// \throws std::runtime_error if file could be opened or if DataSet + /// elements could not be converted to XML + /// + void Save(const std::string& outputFilename); + + /// \brief Saves dataset XML to output stream, e.g. std::cout, + /// std::stringstream. + /// + /// \param[out] out destination for XML contents + /// + /// \throws std::runtime_error if DataSet elements could not be converted to + /// XML + /// + void SaveToStream(std::ostream& out); + +public: + /// + /// \returns true if dataset was read from XML input + /// + bool FromInputXml() const; + + /// + /// \brief Indicate that dataset was read from XML input + /// + void FromInputXml(bool ok); + + /// + /// \returns (absolute) path for dataset + /// + const std::string& Path() const; + + /// + /// \brief Set dataset path + /// + void Path(const std::string& path); + +private: + NamespaceRegistry registry_; + std::string path_; + bool fromInputXml_ = false; +}; + +/// \brief The AlignmentSet class represents an %AlignmentSet root element in +/// DataSetXML. +/// +class PBBAM_EXPORT AlignmentSet : public DataSetBase +{ +public: + /// \brief Creates an empty AlignmentSet dataset. + AlignmentSet(); + AlignmentSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The BarcodeSet class represents a %BarcodeSet root element in +/// DataSetXML. +/// +class PBBAM_EXPORT BarcodeSet : public DataSetBase +{ +public: + /// \brief Creates an empty BarcodeSet dataset. + BarcodeSet(); + BarcodeSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The ConsensusAlignmentSet class represents a %ConsensusAlignmentSet +/// root element in DataSetXML. +/// +class PBBAM_EXPORT ConsensusAlignmentSet : public DataSetBase +{ +public: + /// \brief Creates an empty ConsensusAlignmentSet dataset. + ConsensusAlignmentSet(); + ConsensusAlignmentSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The ConsensusReadSet class represents a %ConsensusReadSet root +/// element in DataSetXML. +/// +class PBBAM_EXPORT ConsensusReadSet : public DataSetBase +{ +public: + /// \brief Creates an empty ConsensusReadSet dataset. + ConsensusReadSet(); + ConsensusReadSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The ContigSet class represents a %ContigSet root element in +/// DataSetXML. +/// +class PBBAM_EXPORT ContigSet : public DataSetBase +{ +public: + /// \brief Creates an empty ContigSet dataset. + ContigSet(); + ContigSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The HdfSubreadSet class represents a %HdfSubreadSet root element in +/// DataSetXML. +/// +class PBBAM_EXPORT HdfSubreadSet : public DataSetBase +{ +public: + /// \brief Creates an empty HdfSubreadSet dataset. + HdfSubreadSet(); + HdfSubreadSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The ReferenceSet class represents a %ReferenceSet root element in +/// DataSetXML. +/// +class PBBAM_EXPORT ReferenceSet : public DataSetBase +{ +public: + /// \brief Creates an empty ReferenceSet dataset. + ReferenceSet(); + ReferenceSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The SubDataSets class represents a %DataSets list element in +/// DataSetXML. +/// +/// The SubDataSets element is essentially a list of DataSets. +/// +class PBBAM_EXPORT SubDataSets : public internal::DataSetElement +{ +public: + /// \brief Creates an empty list of sub-datasets. + SubDataSets(); + SubDataSets(const internal::FromInputXml& fromInputXml); + +public: + /// \brief Adds \p other sub-dataset to this list. + SubDataSets& operator+=(const DataSetBase& other); // single + + /// \brief Adds \p other sub-dataset list to this list. + SubDataSets& operator+=(const SubDataSets& other); // list + +public: + /// \brief Adds a sub-dataset to this list. + void Add(const DataSetBase& subdataset); + + /// \brief Removes a sub-dataset from this list. + void Remove(const DataSetBase& subdataset); + +public: + using value_type = DataSetBase; + using iterator_type = internal::DataSetElementIterator; + using const_iterator_type = internal::DataSetElementConstIterator; + + const value_type& operator[](size_t index) const; + value_type& operator[](size_t index); + + iterator_type begin(); + const_iterator_type begin() const; + const_iterator_type cbegin() const; + iterator_type end(); + const_iterator_type end() const; + const_iterator_type cend() const; +}; + +/// \brief The SubreadSet class represents a %SubreadSet root element in +/// DataSetXML. +/// +class PBBAM_EXPORT SubreadSet : public DataSetBase +{ +public: + /// \brief Creates an empty SubreadSet dataset. + SubreadSet(); + SubreadSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The TranscriptSet class represents a %TranscriptSet root element in +/// DataSetXML. +/// +class PBBAM_EXPORT TranscriptSet : public DataSetBase +{ +public: + /// \brief Creates an empty TranscriptSet dataset. + TranscriptSet(); + TranscriptSet(const internal::FromInputXml& fromInputXml); +}; + +/// \brief The TranscriptAlignmentSet class represents a %TranscriptAlignmentSet +/// root element in DataSetXML. +/// +class PBBAM_EXPORT TranscriptAlignmentSet : public DataSetBase +{ +public: + /// \brief Creates an empty TranscriptAlignmentSet dataset. + TranscriptAlignmentSet(); + TranscriptAlignmentSet(const internal::FromInputXml& fromInputXml); +}; + +enum class XmlElementType +{ + GENERIC_ELEMENT, + DATASET_METADATA, + BIOSAMPLE, + BIOSAMPLES, + DNA_BARCODE, + DNA_BARCODES, + EXTENSION, + EXTENSIONS, + EXTERNAL_RESOURCE, + EXTERNAL_RESOURCES, + FILE_INDEX, + FILE_INDICES, + FILTER, + FILTERS, + PARENT_TOOL, + PROPERTY, + PROPERTIES, + PROVENANCE, + + GENERIC_DATASET, + ALIGNMENT_SET, + BARCODE_SET, + CONSENSUS_ALIGNMENT_SET, + CONSENSUS_READ_SET, + CONTIG_SET, + HDF_SUBREAD_SET, + REFERENCE_SET, + SUBREAD_SET, + TRANSCRIPT_SET, + TRANSCRIPT_ALIGNMENT_SET, + SUBDATASETS +}; + +/// \returns the enum value for the requested XML element +/// (generic if not a built-in element type) +XmlElementType ElementTypeFromName(const std::string& name); + +} // namespace BAM +} // namespace PacBio + +#endif // DATASETTYPES_H diff --git a/include/pbbam/DataSetXsd.h b/include/pbbam/DataSetXsd.h new file mode 100644 index 0000000..df18595 --- /dev/null +++ b/include/pbbam/DataSetXsd.h @@ -0,0 +1,116 @@ +// File Description +/// \file DataSetXsd.h +/// \brief Defines the XSD- and namespace-related classes for DataSetXML. +// +// Author: Derek Barnett + +#ifndef DATASETXSD_H +#define DATASETXSD_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +/// \brief The XsdType enum defines the supported XSD namespaces. +/// +enum class XsdType +{ + NONE, + AUTOMATION_CONSTRAINTS, + BASE_DATA_MODEL, + COLLECTION_METADATA, + COMMON_MESSAGES, + DATA_MODEL, + DATA_STORE, + DATASETS, + DECL_DATA, + PART_NUMBERS, + PRIMARY_METRICS, + REAGENT_KIT, + RIGHTS_AND_ROLES, + SAMPLE_INFO, + SEEDING_DATA +}; + +/// \brief The NamespaceInfo class provides XML namespace info (prefix & URI). +/// +class PBBAM_EXPORT NamespaceInfo +{ +public: + /// \brief Creates an empty entry. + /// + /// This constructor only exists for STL container compatibility. + /// + NamespaceInfo() = default; + + /// \brief Creates a valid info entry. + NamespaceInfo(std::string name, std::string uri); + +public: + /// \brief Fetches namespace name (i.e. prefix) + const std::string& Name() const; + + /// \brief Fetches namespace URI. + const std::string& Uri() const; + +private: + std::string name_; + std::string uri_; +}; + +/// \brief The NamespaceRegistry class provides a per-dataset registry of XML +/// namespace information. +/// +/// This is used to format XML output - properly prefixing element labels with +/// namespace as appropriate. +/// +class PBBAM_EXPORT NamespaceRegistry +{ +public: + /// \name Constructors & Related Methods + /// \{ + + NamespaceRegistry(); + + /// \} + +public: + /// \name Registry Access + /// \{ + + /// \brief Fetches namespace info for the dataset's default XSD type. + const NamespaceInfo& DefaultNamespace() const; + + /// \brief Fetches dataset's default XSD type. + XsdType DefaultXsd() const; + + /// \brief Fetches namespace info for the requested XSD type. + const NamespaceInfo& Namespace(const XsdType& xsd) const; + + /// \brief Registers namespace info for a particular XSD type. + void Register(const XsdType& xsd, const NamespaceInfo& namespaceInfo); + + /// \brief Updates dataset's default XSD type. + void SetDefaultXsd(const XsdType& xsd); + + /// \brief Fetches the XSD type for \p elementLabel. + XsdType XsdForElement(const std::string& elementLabel) const; + + /// \brief Fetches the XSD type for a particular URI. + XsdType XsdForUri(const std::string& uri) const; + + /// \} + +private: + std::map data_; + XsdType defaultXsdType_ = XsdType::DATASETS; +}; + +} // namespace PacBio +} // namespace BAM + +#endif // DATASETXSD_H diff --git a/include/pbbam/EntireFileQuery.h b/include/pbbam/EntireFileQuery.h new file mode 100644 index 0000000..2d15fa7 --- /dev/null +++ b/include/pbbam/EntireFileQuery.h @@ -0,0 +1,65 @@ +// File Description +/// \file EntireFileQuery.h +/// \brief Defines the EntireFileQuery class. +// +// Author: Derek Barnett + +#ifndef ENTIREFILEQUERY_H +#define ENTIREFILEQUERY_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The EntireFileQuery class provides iterable access to a DataSet's +/// %BAM records, reading through the entire contents of each file. +/// +/// Input files will be accessed in the order listed in the DataSet. +/// +/// \include code/EntireFileQuery.txt +/// +/// Iteration is not limited to only 'const' records. The files themselves will +/// not be affected, but individual records may be modified if needed. +/// +/// \include code/EntireFileQuery_NonConst.txt +/// +/// \note DataSets can be implicitly constructed from %BAM filenames as well. +/// Thus a single %BAM file can be read through using the following: +/// +/// \include code/EntireFileQuery_BamFilename.txt +/// +class PBBAM_EXPORT EntireFileQuery : public internal::IQuery +{ +public: + /// \brief Creates a new EntireFileQuery, reading through the entire + /// contents of a dataset. + /// + /// \param[in] dataset input data source(s) + /// \throws std::runtime_error on failure to open/read underlying %BAM + /// files. + /// + EntireFileQuery(const PacBio::BAM::DataSet& dataset); + ~EntireFileQuery() override; + +public: + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(BamRecord& r) override; + +private: + class EntireFileQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ENTIREFILEQUERY_H diff --git a/include/pbbam/FaiIndex.h b/include/pbbam/FaiIndex.h new file mode 100644 index 0000000..a830058 --- /dev/null +++ b/include/pbbam/FaiIndex.h @@ -0,0 +1,101 @@ +// File Description +/// \file FaiIndex.h +/// \brief Defines the FaiIndex class. +// +// Author: Derek Barnett + +#ifndef FAIINDEX_H +#define FAIINDEX_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +struct FaiEntry +{ + /// Total length of this reference sequence, in bases + uint64_t Length = 0; + + /// Offset in the FASTA/FASTQ file of this sequence's first base + uint64_t SeqOffset = 0; + + /// The number of bases on each line + uint16_t NumBases = 0; + + // The number of bytes in each line, including the newline (allows for Windows newlines) + uint16_t NumBytes = 0; + + // Offset of sequence's first quality within the FASTQ file (-1 if FASTA only) + int64_t QualOffset = -1; +}; + +class FaiIndex +{ +public: + /// + /// \brief Load FAI data from \p fn (*.fai) + /// + explicit FaiIndex(const std::string& fn); + + FaiIndex(); + FaiIndex(FaiIndex&&) noexcept; + FaiIndex& operator=(FaiIndex&&) noexcept; + ~FaiIndex(); + + /// + /// \brief Add new FAI line to index + /// + void Add(std::string name, FaiEntry entry); + + /// + /// \returns FAI entry for sequence name + /// + const FaiEntry& Entry(const std::string& name) const; + + /// + /// \returns FAI entry at \p row + /// + const FaiEntry& Entry(const uint32_t row) const; + + /// + /// \returns true if sequence name found in index + /// + bool HasEntry(const std::string& name) const; + + /// + /// \returns sequence names in FAI file + /// + const std::vector& Names() const; + + /// + /// \brief Save FAI data to file + /// + void Save(const std::string& fn) const; + + /// + /// \brief Save FAI data to output stream + /// + void Save(std::ostream& out) const; + +private: + class FaiIndexPrivate; + std::unique_ptr d_; +}; + +bool operator==(const FaiEntry& lhs, const FaiEntry& rhs); + +// NOTE: FaiEntry output *does not* include the name column, FaiIndex::Save() +// handles this mapping +std::ostream& operator<<(std::ostream& out, const FaiEntry& entry); + +} // namespace BAM +} // namespace PacBio + +#endif // FAIINDEX_H diff --git a/include/pbbam/FastaCache.h b/include/pbbam/FastaCache.h new file mode 100644 index 0000000..ab91a6f --- /dev/null +++ b/include/pbbam/FastaCache.h @@ -0,0 +1,60 @@ +// File Description +/// \file FastaCache.h +/// \brief Defines the FastaCache +// +// Author: Derek Barnett + +#ifndef FASTACACHE_H +#define FASTACACHE_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include "pbbam/FastaSequence.h" + +namespace PacBio { +namespace BAM { + +class FastaCacheData +{ +public: + explicit FastaCacheData(const std::string& filename); + + /// \brief Fetches FASTA sequence for desired interval. + /// + /// \param[in] name reference sequence name + /// \param[in] begin start position + /// \param[in] end end position + /// + /// \returns sequence string at desired interval + /// + /// \throws std::runtime_error on failure to fetch sequence + /// + std::string Subsequence(const std::string& name, size_t begin, size_t end) const; + + /// \returns the names of all sequences stored in the FASTA file + std::vector Names() const; + + /// \returns length of FASTA sequence + /// + /// \throws std::runtime_error if name is unknown + /// + size_t SequenceLength(const std::string& name) const; + +private: + std::vector cache_; + std::unordered_map lookup_; +}; + +using FastaCache = std::shared_ptr; + +FastaCache MakeFastaCache(const std::string& filename); + +} // namespace BAM +} // namespace PacBio + +#endif // FASTACACHE_H diff --git a/include/pbbam/FastaReader.h b/include/pbbam/FastaReader.h new file mode 100644 index 0000000..daa2c30 --- /dev/null +++ b/include/pbbam/FastaReader.h @@ -0,0 +1,85 @@ +// File Description +/// \file FastaReader.h +/// \brief Defines the FastaReader class. +// +// Author: Derek Barnett + +#ifndef FASTAREADER_H +#define FASTAREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/FastaSequence.h" + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// +/// \brief The FastaReader provides sequential access to FASTA records. +/// +class FastaReader : public internal::QueryBase +{ +public: + /// + /// \brief Reads all FASTA sequences from a file + /// + /// \param fn FASTA filename + /// \return vector of FastaSequence results + /// + static std::vector ReadAll(const std::string& fn); + +public: + /// \name Constructors & Related Methods + /// \{ + + explicit FastaReader(const std::string& fn); + + FastaReader(FastaReader&&) noexcept; + FastaReader& operator=(FastaReader&&) noexcept; + ~FastaReader(); + + /// \} + +public: + /// + /// \brief GetNext + /// + /// Allows iteration with range-for: + /// \code{cpp} + /// + /// FastaReader reader{fn}; + /// for (const FastaSequence& seq : reader) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// or you can iterate 'manually': + /// \code{cpp} + /// + /// FastaReader reader{fn}; + /// FastaSequence seq; + /// while (reader.GetNext(seq)) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// \param[out] record + /// \return success/failure + /// + bool GetNext(FastaSequence& record); + +private: + class FastaReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FASTAREADER_H diff --git a/include/pbbam/FastaSequence.h b/include/pbbam/FastaSequence.h new file mode 100644 index 0000000..ef769dd --- /dev/null +++ b/include/pbbam/FastaSequence.h @@ -0,0 +1,82 @@ +// File Description +/// \file FastaSequence.h +/// \brief Defines the FastaSequence class. +// +// Author: Derek Barnett + +#ifndef FASTASEQUENCE_H +#define FASTASEQUENCE_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +/// +/// \brief The FastaSequence class represents a FASTA record (name & bases) +/// +class FastaSequence +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// + /// \brief FastaSequence + /// \param name + /// \param bases + /// + explicit FastaSequence(std::string name, std::string bases); + + FastaSequence() = default; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// + /// \brief Name + /// \return + /// + const std::string& Name() const; + + /// + /// \brief + /// + /// \param name + /// \return FastaSequence& + /// + FastaSequence& Name(std::string name); + + /// + /// \brief Bases + /// \return + /// + const std::string& Bases() const; + + /// + /// \brief + /// + /// \param bases + /// \return FastaSequence& + /// + FastaSequence& Bases(std::string bases); + + /// \} + + bool operator==(const FastaSequence& other) const; + bool operator!=(const FastaSequence& other) const; + +private: + std::string name_; + std::string bases_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FASTASEQUENCE_H diff --git a/include/pbbam/FastaSequenceQuery.h b/include/pbbam/FastaSequenceQuery.h new file mode 100644 index 0000000..0886c6b --- /dev/null +++ b/include/pbbam/FastaSequenceQuery.h @@ -0,0 +1,52 @@ +// File Description +/// \file FastaSequenceQuery.h +/// \brief Defines the FastaSequenceQuery class. +// +// Author: Derek Barnett + +#ifndef FASTASEQUENCEQUERY_H +#define FASTASEQUENCEQUERY_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/DataSet.h" +#include "pbbam/FastaSequence.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// +/// \brief The FastaSequence class represents a FASTA record (name & bases) +/// +class FastaSequenceQuery : public internal::QueryBase +{ +public: + /// \name Constructors & Related Methods + /// \{ + + FastaSequenceQuery(const PacBio::BAM::DataSet& dataset); + ~FastaSequenceQuery() override; + + /// \} + +public: + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(FastaSequence& seq) override; + +private: + class FastaSequenceQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FASTASEQUENCEQUERY_H diff --git a/include/pbbam/FastaWriter.h b/include/pbbam/FastaWriter.h new file mode 100644 index 0000000..3cbfd9f --- /dev/null +++ b/include/pbbam/FastaWriter.h @@ -0,0 +1,47 @@ +// File Description +/// \file FastaWriter.h +/// \brief Defines the FastaWriter class. +// +// Author: Derek Barnett + +#ifndef FASTAWRITER_H +#define FASTAWRITER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/IFastaWriter.h" + +namespace PacBio { +namespace BAM { + +class BamRecord; +class BamRecordImpl; +class FastaSequence; + +class FastaWriter final : public IFastaWriter +{ +public: + FastaWriter(const std::string& fn); + +public: + // IFastaWriter + void Write(const FastaSequence& fastq); + void Write(const std::string& name, const std::string& bases); + + // IRecordWriter + void TryFlush(); + void Write(const BamRecord& bam); + void Write(const BamRecordImpl& bam); + +private: + std::ofstream file_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FASTAWRITER_H diff --git a/include/pbbam/FastqReader.h b/include/pbbam/FastqReader.h new file mode 100644 index 0000000..18c2c70 --- /dev/null +++ b/include/pbbam/FastqReader.h @@ -0,0 +1,85 @@ +// File Description +/// \file FastqReader.h +/// \brief Defines the FastqReader class. +// +// Author: Derek Barnett + +#ifndef FASTQREADER_H +#define FASTQREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/FastqSequence.h" + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// +/// \brief The FastqReader provides sequential access to Fastq records. +/// +class FastqReader : public internal::QueryBase +{ +public: + /// + /// \brief Reads all Fastq sequences from a file + /// + /// \param fn Fastq filename + /// \return vector of FastqSequence results + /// + static std::vector ReadAll(const std::string& fn); + +public: + /// \name Constructors & Related Methods + /// \{ + + explicit FastqReader(const std::string& fn); + + FastqReader(FastqReader&&) noexcept; + FastqReader& operator=(FastqReader&&) noexcept; + virtual ~FastqReader(); + + /// \} + +public: + /// + /// \brief GetNext + /// + /// Allows iteration with range-for: + /// \code{cpp} + /// + /// FastqReader reader{fn}; + /// for (const FastqSequence& seq : reader) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// or you can iterate 'manually': + /// \code{cpp} + /// + /// FastqReader reader{fn}; + /// FastqSequence seq; + /// while (reader.GetNext(seq)) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// \param[out] record + /// \return success/failure + /// + bool GetNext(FastqSequence& record); + +private: + class FastqReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FASTQREADER_H diff --git a/include/pbbam/FastqSequence.h b/include/pbbam/FastqSequence.h new file mode 100644 index 0000000..0f48d35 --- /dev/null +++ b/include/pbbam/FastqSequence.h @@ -0,0 +1,80 @@ +// File Description +/// \file FastqSequence.h +/// \brief Defines the FastqSequence class. +// +// Author: Derek Barnett + +#ifndef FASTQSEQUENCE_H +#define FASTQSEQUENCE_H + +#include "pbbam/Config.h" + +#include + +#include +#include + +namespace PacBio { +namespace BAM { + +/// +/// \brief The FastqSequence class represents a FASTQ record (name, bases, and +/// qualities) +/// +class FastqSequence : public FastaSequence +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// + /// \brief FastaSequence + /// \param name + /// \param bases + /// \param qualities + /// + explicit FastqSequence(std::string name, std::string bases, QualityValues qualities); + + /// + /// \brief FastaSequence + /// \param name + /// \param bases + /// \param qualities + /// + explicit FastqSequence(std::string name, std::string bases, std::string qualities); + + FastqSequence() = default; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// + /// \brief Qualities + /// \return + /// + const QualityValues& Qualities() const; + + /// + /// \brief + /// + /// \param quals + /// \return FastqSequence + /// + FastqSequence& Qualities(QualityValues quals); + + /// \} + + bool operator==(const FastqSequence& other) const; + bool operator!=(const FastqSequence& other) const; + +private: + QualityValues qualities_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FASTQSEQUENCE_H diff --git a/include/pbbam/FastqWriter.h b/include/pbbam/FastqWriter.h new file mode 100644 index 0000000..cb38d74 --- /dev/null +++ b/include/pbbam/FastqWriter.h @@ -0,0 +1,48 @@ +// File Description +/// \file FastqWriter.h +/// \brief Defines the FastqWriter class. +// +// Author: Derek Barnett + +#ifndef FASTQWRITER_H +#define FASTQWRITER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/IFastqWriter.h" + +namespace PacBio { +namespace BAM { + +class BamRecord; +class BamRecordImpl; +class FastqSequence; + +class FastqWriter final : public IFastqWriter +{ +public: + FastqWriter(const std::string& fn); + +public: + // IFastqWriter + void Write(const FastqSequence& fastq); + void Write(const std::string& name, const std::string& bases, const QualityValues& quals); + void Write(const std::string& name, const std::string& bases, const std::string& quals); + + // IRecordWriter + void TryFlush(); + void Write(const BamRecord& bam); + void Write(const BamRecordImpl& bam); + +private: + std::ofstream file_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FASTQWRITER_H diff --git a/include/pbbam/FormatUtils.h b/include/pbbam/FormatUtils.h new file mode 100644 index 0000000..e301320 --- /dev/null +++ b/include/pbbam/FormatUtils.h @@ -0,0 +1,44 @@ +// Author: Derek Barnett + +#ifndef FORMAT_UTILS_H +#define FORMAT_UTILS_H + +#include "pbbam/Config.h" + +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +enum class HtslibCompression +{ + NONE, + GZIP, + BGZIP +}; + +class FormatUtils +{ +public: + static const std::vector& BedExtensions(); + static const std::vector& FastaExtensions(); + static const std::vector& FastqExtensions(); + + static bool IsBedFilename(const std::string& fn); + static bool IsFastaFilename(const std::string& fn); + static bool IsFastqFilename(const std::string& fn); + + static HtslibCompression CompressionType(BGZF* fp); + static HtslibCompression CompressionType(const std::string& fn); + +private: + static bool IsFormat(const std::string& fn, const std::vector& extensions); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FORMAT_UTILS_H diff --git a/include/pbbam/FrameEncodingType.h b/include/pbbam/FrameEncodingType.h new file mode 100644 index 0000000..f68810f --- /dev/null +++ b/include/pbbam/FrameEncodingType.h @@ -0,0 +1,33 @@ +// File Description +/// \file FrameEncodingType.h +/// \brief Defines the FrameEncodingType enum. +// +// Author: Derek Barnett + +#ifndef FRAMEENCODINGTYPE_H +#define FRAMEENCODINGTYPE_H + +#include "pbbam/Config.h" + +namespace PacBio { +namespace BAM { + +/// \brief This enum defines the possible encoding modes used in Frames data +/// (e.g. BamRecord::IPD or BamRecord::PulseWidth). +/// +/// The LOSSY mode is the default in production output; LOSSLESS mode +/// being used primarily for internal applications. +/// +/// \sa https://github.com/PacificBiosciences/PacBioFileFormats/blob/3.0/BAM.rst +/// for more information on pulse frame encoding schemes. +/// +enum class FrameEncodingType +{ + LOSSY, ///< 8-bit compression (using CodecV1) of frame data + LOSSLESS ///< 16-bit native frame data +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FRAMEENCODINGTYPE_H diff --git a/include/pbbam/Frames.h b/include/pbbam/Frames.h new file mode 100644 index 0000000..eb1a610 --- /dev/null +++ b/include/pbbam/Frames.h @@ -0,0 +1,26 @@ +// File Description +/// \file Frames.h +/// \brief Defines the Frames class. +// +// Author: Derek Barnett + +#ifndef FRAMES_H +#define FRAMES_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +using Frames PBBAM_DEPRECATED = PacBio::Data::Frames; + +} // namespace BAM +} // namespace PacBio + +#endif // FRAMES_H diff --git a/include/pbbam/GenomicInterval.h b/include/pbbam/GenomicInterval.h new file mode 100644 index 0000000..b8d493f --- /dev/null +++ b/include/pbbam/GenomicInterval.h @@ -0,0 +1,22 @@ +// File Description +/// \file GenomicInterval.h +/// \brief Defines the GenomicInterval class. +// +// Author: Derek Barnett + +#ifndef GENOMICINTERVAL_H +#define GENOMICINTERVAL_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +using GenomicInterval PBBAM_DEPRECATED = Data::GenomicInterval; + +} // namespace BAM +} // namespace PacBio + +#endif // GENOMICINTERVAL_H diff --git a/include/pbbam/GenomicIntervalQuery.h b/include/pbbam/GenomicIntervalQuery.h new file mode 100644 index 0000000..ccaa508 --- /dev/null +++ b/include/pbbam/GenomicIntervalQuery.h @@ -0,0 +1,103 @@ +// File Description +/// \file GenomicIntervalQuery.h +/// \brief Defines the GenomicIntervalQuery class. +// +// Author: Derek Barnett + +#ifndef GENOMICINTERVALQUERY_H +#define GENOMICINTERVALQUERY_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/BaiIndexCache.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace Data { + +class GenomicInterval; +} + +namespace BAM { + +class BamRecord; +class DataSet; + +/// \brief The GenomicIntervalQuery class provides iterable access to a +/// DataSet's %BAM records, limiting results to those overlapping a +/// GenomicInterval. +/// +/// Example: +/// \include code/GenomicIntervalQuery.txt +/// +/// \note Currently, all %BAM files must have a corresponding ".bai" index file. +/// Use BamFile::EnsureStandardIndexExists before creating the query if +/// one may not be present. +/// +class PBBAM_EXPORT GenomicIntervalQuery : public internal::IQuery +{ +public: + /// \brief Constructs a new GenomiIntervalQuery, that can be used to retrieve + /// only those records overlapping a GenomicInterval. + /// + /// \note Using this constructor means that an interval must be provided, via + /// query.Interval(i), before iterating. + /// + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or + /// BAI files. + /// + GenomicIntervalQuery(const DataSet& dataset); + GenomicIntervalQuery(const DataSet& dataset, const BaiIndexCache& cache); + + /// \brief Constructs a new GenomiIntervalQuery, limiting record results to + /// only those overalpping a GenomicInterval. + /// + /// \param[in] interval genomic interval of interest + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or + /// BAI files. + /// + GenomicIntervalQuery(const Data::GenomicInterval& interval, const DataSet& dataset); + GenomicIntervalQuery(const Data::GenomicInterval& interval, const DataSet& dataset, + const BaiIndexCache& cache); + + ~GenomicIntervalQuery() override; + +public: + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(BamRecord& r) override; + +public: + /// \brief Sets a new genomic interval. + /// + /// This allows the same dataset/query to be re-used over multiple regions of + /// interest: + /// + /// \include code/GenomicIntervalQuery_Reuse.txt + /// + /// \param[in] interval new genomic interval + /// \returns reference to this query + /// + GenomicIntervalQuery& Interval(const Data::GenomicInterval& interval); + + /// \returns Current genomic interval active on this query. + const Data::GenomicInterval& Interval() const; + +private: + class GenomicIntervalQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // GENOMICINTERVALQUERY_H diff --git a/include/pbbam/IFastaWriter.h b/include/pbbam/IFastaWriter.h new file mode 100644 index 0000000..2573be3 --- /dev/null +++ b/include/pbbam/IFastaWriter.h @@ -0,0 +1,39 @@ +// File Description +/// \file IFastaWriter.h +/// \brief Defines the IFastaWriter interface. +// +// Author: Derek Barnett + +#ifndef IFASTAWRITER_H +#define IFASTAWRITER_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/IRecordWriter.h" + +namespace PacBio { +namespace BAM { + +class FastaSequence; + +class IFastaWriter : public IRecordWriter +{ +public: + virtual ~IFastaWriter(); + +public: + using IRecordWriter::Write; + + virtual void Write(const FastaSequence& fastq) = 0; + virtual void Write(const std::string& name, const std::string& bases) = 0; + +protected: + IFastaWriter(); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // IFASTAWRITER_H diff --git a/include/pbbam/IFastqWriter.h b/include/pbbam/IFastqWriter.h new file mode 100644 index 0000000..3cc8167 --- /dev/null +++ b/include/pbbam/IFastqWriter.h @@ -0,0 +1,43 @@ +// File Description +/// \file IFastqWriter.h +/// \brief Defines the IFastqWriter interface. +// +// Author: Derek Barnett + +#ifndef IFASTQWRITER_H +#define IFASTQWRITER_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/IRecordWriter.h" +#include "pbbam/QualityValues.h" + +namespace PacBio { +namespace BAM { + +class FastqSequence; + +class IFastqWriter : public IRecordWriter +{ +public: + virtual ~IFastqWriter(); + +public: + using IRecordWriter::Write; + + virtual void Write(const FastqSequence& fastq) = 0; + virtual void Write(const std::string& name, const std::string& bases, + const QualityValues& quals) = 0; + virtual void Write(const std::string& name, const std::string& bases, + const std::string& quals) = 0; + +protected: + IFastqWriter(); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // IFASTQWRITER_H diff --git a/include/pbbam/IRecordWriter.h b/include/pbbam/IRecordWriter.h new file mode 100644 index 0000000..fbbcf69 --- /dev/null +++ b/include/pbbam/IRecordWriter.h @@ -0,0 +1,57 @@ +// File Description +/// \file IRecordWriter.h +/// \brief Defines the IRecordWriter interface. +// +// Author: Derek Barnett + +#ifndef IRECORDWRITER_H +#define IRECORDWRITER_H + +#include "pbbam/Config.h" + +namespace PacBio { +namespace BAM { + +class BamRecord; +class BamRecordImpl; + +class IRecordWriter +{ +public: + virtual ~IRecordWriter(); + +public: + /// \brief Try to flush any buffered data to file. + /// + /// \note The underlying implementation may not necessarily flush buffered + /// data immediately, especially in a multithreaded writer situation. + /// Let the writer go out of scope to fully ensure flushing. + /// + /// \throws std::runtime_error if flush fails + /// + virtual void TryFlush() = 0; + + /// \brief Write a record to the output %BAM file. + /// + /// \param[in] record BamRecord object + /// + /// \throws std::runtime_error on failure to write + /// + virtual void Write(const BamRecord& record) = 0; + + /// \brief Write a record to the output %BAM file. + /// + /// \param[in] recordImpl BamRecordImpl object + /// + /// \throws std::runtime_error on failure to write + /// + virtual void Write(const BamRecordImpl& recordImpl) = 0; + +protected: + IRecordWriter(); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // IRECORDWRITER_H diff --git a/include/pbbam/IndexedBamWriter.h b/include/pbbam/IndexedBamWriter.h new file mode 100644 index 0000000..991db8e --- /dev/null +++ b/include/pbbam/IndexedBamWriter.h @@ -0,0 +1,155 @@ +// File Description +/// \file IndexedBamWriter.h +/// \brief Defines the IndexedBamWriter class. +// +// Author: Derek Barnett + +#ifndef INDEXEDBAMWRITER_H +#define INDEXEDBAMWRITER_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/BamWriter.h" +#include "pbbam/IRecordWriter.h" +#include "pbbam/PbiBuilder.h" + +namespace PacBio { +namespace BAM { + +class BamHeader; +class BamRecord; +class BamRecordImpl; + +struct IndexedBamWriterConfig +{ + std::string outputFilename; + BamHeader header; + + BamWriter::CompressionLevel bamCompressionLevel = BamWriter::DefaultCompression; + PbiBuilder::CompressionLevel pbiCompressionLevel = PbiBuilder::DefaultCompression; + + // Number of threads used while writing to BAM file + size_t numBamThreads = 4; + // Number of threads used while writing to pbi file + size_t numPbiThreads = 4; + // Number of threads used while doing a trailing read of the BaM file being + // written (to help compute indexes) + size_t numGziThreads = 4; + + // Max size in memory for temporary files before flushing to disk. + size_t tempFileBufferSize = 0x10000; +}; +/// +/// \brief The IndexedBamWriter class +/// +/// +/// +/// +/// +/// +class IndexedBamWriter : public IRecordWriter +{ +public: + /// + /// \brief IndexedBamWriter + /// + /// \param[in] filename path to output %BAM file + /// \param[in] header BAM file header + /// + /// \param[in] bamCompressionLevel zlib compression level for output BAM + /// \param[in] numBamThreads number of threads for BAM compression. + /// If set to 0, the writer will attempt to + /// determine a reasonable estimate. If set + /// to 1, this will force single-threaded + /// execution. No checks are made against an + /// upper limit. + /// + /// \param[in] pbiCompressionLevel zlib compression level for output PBI + /// \param[in] numPbiThreads number of threads for PBI compression. + /// If set to 0, the writer will attempt to + /// determine a reasonable estimate. If set + /// to 1, this will force single-threaded + /// execution. No checks are made against an + /// upper limit. + /// \param[in] numGziThreads number of threads used by the trailing + /// reader process used to help compute indexes. + /// If set to 0, the writer will attempt to + /// determine a reasonable estimate. If set + /// to 1, this will force single-threaded + /// execution. No checks are made against an + /// upper limit. + /// \param[in] tempFileBufferBytes Maximum number of bytes various temporary + /// files can use before they flush to disk. + /// Larger numbers require more resources but + /// may increase disk IO efficiency. + /// + /// \throws std::runtime_error if there was a problem + /// + IndexedBamWriter( + const std::string& outputFilename, const BamHeader& header, + const BamWriter::CompressionLevel bamCompressionLevel = BamWriter::DefaultCompression, + const size_t numBamThreads = 4, + const PbiBuilder::CompressionLevel pbiCompressionLevel = PbiBuilder::DefaultCompression, + const size_t numPbiThreads = 4, const size_t numGziThreads = 4, + const size_t tempFileBufferSize = 0x10000); + + /// \brief IndexedBamWRiter + /// + /// \param[in] config Struct containing all the parameters used to construct + /// this object. See documentation for other constructor + /// for more details + IndexedBamWriter(const IndexedBamWriterConfig& config) + : IndexedBamWriter(config.outputFilename, config.header, config.bamCompressionLevel, + config.numBamThreads, config.pbiCompressionLevel, config.numPbiThreads, + config.numGziThreads, config.tempFileBufferSize) + { + } + + IndexedBamWriter(IndexedBamWriter&&) noexcept; + IndexedBamWriter& operator=(IndexedBamWriter&&) noexcept; + ~IndexedBamWriter(); + +public: + /// + /// \brief TryFlush + /// + void TryFlush() override; + + /// + /// \brief Write + /// + /// \param[in] record + /// + void Write(const BamRecord& record) override; + + /// + /// \brief Write + /// + /// \param[in] record + /// + void Write(const BamRecordImpl& record) override; + + /// \brief ReaderTrailingDistance + /// + /// Allows calling code to monitor how far behind (in bytes) + /// the reader thread trails behind the tip of the current + /// being written BAM file. May be useful for diagnosing + /// performance issues if the reader thread falls enough behind + /// that caching is insufficient to prevent an IO hit from the + /// extra read operations. + /// + /// Note: Returns a "high water mark", not a current value. + size_t MaxReaderLag() const; + +private: + class IndexedBamWriterPrivate2; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // INDEXEDBAMWRITER_H diff --git a/include/pbbam/IndexedFastaReader.h b/include/pbbam/IndexedFastaReader.h new file mode 100644 index 0000000..7f9ac8d --- /dev/null +++ b/include/pbbam/IndexedFastaReader.h @@ -0,0 +1,147 @@ +// File Description +/// \file IndexedFastaReader.h +/// \brief Defines the IndexedFastaReader class. +// +// Author: David Alexander + +#ifndef INDEXEDFASTAREADER_H +#define INDEXEDFASTAREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include +#include + +#include "pbbam/Orientation.h" +#include "pbbam/Position.h" + +namespace PacBio { +namespace Data { + +class GenomicInterval; +} + +namespace BAM { + +class BamRecord; + +/// \brief The IndexedFastaReader class provides random-access to FASTA file +/// data. +/// +class IndexedFastaReader +{ + +public: + /// \name Constructors & Related Methods + /// \{ + + explicit IndexedFastaReader(std::string filename); + + IndexedFastaReader(const IndexedFastaReader&); + IndexedFastaReader(IndexedFastaReader&&) noexcept; + IndexedFastaReader& operator=(const IndexedFastaReader&); + IndexedFastaReader& operator=(IndexedFastaReader&&) noexcept; + ~IndexedFastaReader(); + + /// \} + +public: + /// name Sequence Access + /// \{ + + /// \brief Fetches FASTA sequence for desired interval. + /// + /// \param[in] id reference sequence name + /// \param[in] begin start position + /// \param[in] end end position + /// + /// \returns sequence string at desired interval + /// + /// \throws std::runtime_error on failure to fetch sequence + /// + std::string Subsequence(const std::string& id, Position begin, Position end) const; + + /// \brief Fetches FASTA sequence for desired interval. + /// + /// \param[in] interval desired interval + /// + /// \returns sequence string at desired interval + /// + /// \throws std::runtime_error on failure to fetch sequence + /// + std::string Subsequence(const Data::GenomicInterval& interval) const; + + /// \brief Fetches FASTA sequence for desired interval. + /// + /// \param[in] htslibRegion htslib/samtools-formatted REGION string + /// representing the desired interval + /// + /// \returns sequence string at desired interval + /// + /// \throws std::runtime_error on failure to fetch sequence + /// + std::string Subsequence(const char* htslibRegion) const; + + /// \brief Fetches FASTA sequence corresponding to a BamRecord, oriented and + /// gapped as requested. + /// + /// For example, "native" orientation and "gapped" will return the reference + /// sequence with gaps inserted, as would align against the read in "native" + /// orientation. + /// + /// \param[in] bamRecord input BamRecord to derive interval/CIGAR + /// data + /// \param[in] orientation orientation of output + /// \param[in] gapped if true, gaps/padding will be inserted, per + /// record's CIGAR info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns sequence string over the record's interval + /// + /// \throws std::runtime_error on failure to fetch sequence + /// + std::string ReferenceSubsequence(const BamRecord& bamRecord, + const Orientation orientation = Orientation::GENOMIC, + const bool gapped = false, + const bool exciseSoftClips = false) const; + + /// \} + +public: + /// \name File Attributes + /// \{ + + /// \returns true if FASTA file contains a sequence matching \p name + bool HasSequence(const std::string& name) const; + + /// \returns the names of the sequence at a specific index in the FASTA file + std::string Name(const size_t idx) const; + + /// \returns the names of all sequences stored in the FASTA file + std::vector Names() const; + + /// \returns number of sequences stored in FASTA file + int NumSequences() const; + + /// \returns length of FASTA sequence + /// + /// \throws std::runtime_error if length could not be determined + /// + int SequenceLength(const std::string& name) const; + + /// \} + +private: + class IndexedFastaReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // INDEXEDFASTAREADER_H diff --git a/include/pbbam/IndexedFastqReader.h b/include/pbbam/IndexedFastqReader.h new file mode 100644 index 0000000..e4fc6e4 --- /dev/null +++ b/include/pbbam/IndexedFastqReader.h @@ -0,0 +1,141 @@ +// File Description +/// \file IndexedFastqReader.h +/// \brief Defines the IndexedFastqReader class. +// +// Author: Derek Barnett + +#ifndef INDEXEDFASTQREADER_H +#define INDEXEDFASTQREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "pbbam/FastqReader.h" +#include "pbbam/Orientation.h" +#include "pbbam/Position.h" +#include "pbbam/QualityValues.h" + +#include "internal/QueryBase.h" + +namespace PacBio { +namespace Data { + +class GenomicInterval; +} + +namespace BAM { + +class BamRecord; +class IndexedFastqReaderImpl; + +/// \brief The IndexedFastaReader class provides random-access to FASTQ file +/// data. +/// +class IndexedFastqReader +{ + +public: + /// \name Constructors & Related Methods + /// \{ + + explicit IndexedFastqReader(std::string filename); + + IndexedFastqReader(const IndexedFastqReader&); + IndexedFastqReader(IndexedFastqReader&&) noexcept; + IndexedFastqReader& operator=(const IndexedFastqReader& rhs); + IndexedFastqReader& operator=(IndexedFastqReader&&) noexcept; + ~IndexedFastqReader(); + + /// \} + +public: + /// name Sequence Access + /// \{ + + /// \brief Fetches sequence & qualities for desired interval. + /// + /// \param[in] id reference sequence name + /// \param[in] start start position + /// \param[in] end end position + /// + /// \returns sequence/QV pair for desired interval + /// + /// \throws std::runtime_error on failure to fetch data + /// + std::pair Subsequence(const std::string& id, Position start, + Position end); + + /// \brief Fetches sequence & qualities for desired interval. + /// + /// \param[in] interval desired interval + /// + /// \returns sequence/QV pair for desired interval + /// + /// \throws std::runtime_error on failure to fetch data + /// + std::pair Subsequence(const Data::GenomicInterval& interval); + + /// \brief Fetches sequence & qualities sequence corresponding to a BamRecord, oriented and + /// gapped as requested. + /// + /// For example, "native" orientation and "gapped" will return the reference + /// sequence with gaps inserted, as would align against the read in "native" + /// orientation. + /// + /// \param[in] bamRecord input BamRecord to derive interval/CIGAR + /// data + /// \param[in] orientation orientation of output + /// \param[in] gapped if true, gaps/padding will be inserted, per + /// record's CIGAR info. + /// \param[in] exciseSoftClips if true, any soft-clipped positions will be + /// removed from query ends + /// + /// \returns sequence/QV pair over the record's interval + /// + /// \throws std::runtime_error on failure to fetch data + /// + std::pair ReferenceSubsequence( + const BamRecord& bamRecord, const Orientation orientation = Orientation::GENOMIC, + const bool gapped = false, const bool exciseSoftClips = false); + + /// \} + +public: + /// \name File Attributes + /// \{ + + /// \returns true if FASTQ file contains a sequence matching \p name + bool HasSequence(const std::string& name) const; + + /// \returns the names of the sequence at a specific index in the FASTQ file + std::string Name(const size_t idx) const; + + /// \returns the names of all sequences stored in the FASTQ file + std::vector Names() const; + + /// \returns number of sequences stored in FASTQ file + int NumSequences() const; + + /// \returns length of FASTQ sequence + /// + /// \throws std::runtime_error if length could not be determined + /// + int SequenceLength(const std::string& name) const; + + /// \} + +private: + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // INDEXEDFASTQREADER_H diff --git a/include/pbbam/Interval.h b/include/pbbam/Interval.h new file mode 100644 index 0000000..2fb2205 --- /dev/null +++ b/include/pbbam/Interval.h @@ -0,0 +1,22 @@ +// File Description +/// \file Interval.h +/// \brief Defines the Interval class. +// +// Author: Derek Barnett + +#ifndef INTERVAL_H +#define INTERVAL_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +using Interval PBBAM_DEPRECATED = Data::Interval; + +} // namespace BAM +} // namespace PacBio + +#endif // GENOMICINTERVAL_H diff --git a/include/pbbam/LocalContextFlags.h b/include/pbbam/LocalContextFlags.h new file mode 100644 index 0000000..2de7724 --- /dev/null +++ b/include/pbbam/LocalContextFlags.h @@ -0,0 +1,35 @@ +// File Description +/// \file LocalContextFlags.h +/// \brief Defines the LocalContextFlags enum & helper method(s). +// +// Author: Lance Hepler + +#ifndef LOCALCONTEXTFLAGS_H +#define LOCALCONTEXTFLAGS_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +using LocalContextFlags PBBAM_DEPRECATED = PacBio::Data::LocalContextFlags; + +// because LocalContextFlags was a C enum and not a +// C++11 enum class, we need to import all enumerations +// into the containing scope +using PacBio::Data::LocalContextFlags::NO_LOCAL_CONTEXT; +using PacBio::Data::LocalContextFlags::ADAPTER_BEFORE; +using PacBio::Data::LocalContextFlags::ADAPTER_AFTER; +using PacBio::Data::LocalContextFlags::BARCODE_BEFORE; +using PacBio::Data::LocalContextFlags::BARCODE_AFTER; +using PacBio::Data::LocalContextFlags::FORWARD_PASS; +using PacBio::Data::LocalContextFlags::REVERSE_PASS; +using PacBio::Data::LocalContextFlags::ADAPTER_BEFORE_BAD; +using PacBio::Data::LocalContextFlags::ADAPTER_AFTER_BAD; + +} // namespace BAM +} // namespace PacBio + +#endif // LOCALCONTEXTFLAGS_H diff --git a/include/pbbam/MD5.h b/include/pbbam/MD5.h new file mode 100644 index 0000000..de3e3fb --- /dev/null +++ b/include/pbbam/MD5.h @@ -0,0 +1,24 @@ +// File Description +/// \file MD5.h +/// \brief Defines basic MD5 hash utilities +// +// Author: Brett Bowman + +#ifndef MD5_H +#define MD5_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +/// \brief MD5 hash of a string as a 32-digit hexadecimal string +/// +std::string MD5Hash(const std::string& str); + +} // namespace BAM +} // namespace PacBio + +#endif // MD5_H diff --git a/include/pbbam/MoveAppend.h b/include/pbbam/MoveAppend.h new file mode 100644 index 0000000..5cb243d --- /dev/null +++ b/include/pbbam/MoveAppend.h @@ -0,0 +1,52 @@ +// Author: Derek Barnett + +#ifndef MOVEAPPEND_H +#define MOVEAPPEND_H + +#include "pbbam/Config.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { + +// \brief Appends content of src vector to dst vector using move semantics. +/// +/// \param[in] src Input vector that will be empty after execution +/// \param[in,out] dst Output vector that will be appended to +/// +template +inline void MoveAppend(std::vector& src, std::vector& dst) noexcept +{ + if (dst.empty()) { + dst = std::move(src); + } else { + dst.reserve(dst.size() + src.size()); + std::move(src.begin(), src.end(), std::back_inserter(dst)); + src.clear(); + } +} + +/// \brief Appends content of src vector to dst vector using move semantics. +/// +/// \param[in] src Input vector via perfect forwarding +/// \param[in,out] dst Output vector that will be appended to +/// +template +inline void MoveAppend(std::vector&& src, std::vector& dst) noexcept +{ + if (dst.empty()) { + dst = std::move(src); + } else { + dst.reserve(dst.size() + src.size()); + std::move(src.begin(), src.end(), std::back_inserter(dst)); + src.clear(); + } +} + +} // namespace BAM +} // namespace PacBio + +#endif // MOVEAPPEND_H diff --git a/include/pbbam/Orientation.h b/include/pbbam/Orientation.h new file mode 100644 index 0000000..a1241e9 --- /dev/null +++ b/include/pbbam/Orientation.h @@ -0,0 +1,22 @@ +// File Description +/// \file Orientation.h +/// \brief Defines the Orientation enum. +// +// Author: Derek Barnett + +#ifndef ORIENTATION_H +#define ORIENTATION_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +using Orientation PBBAM_DEPRECATED = PacBio::Data::Orientation; + +} // namespace BAM +} // namespace PacBio + +#endif // ORIENTATION_H \ No newline at end of file diff --git a/include/pbbam/PbiBasicTypes.h b/include/pbbam/PbiBasicTypes.h new file mode 100644 index 0000000..286251a --- /dev/null +++ b/include/pbbam/PbiBasicTypes.h @@ -0,0 +1,78 @@ +// File Description +/// \file PbiBasicTypes.h +/// \brief Defines the basic data structures used in PBI lookups. +// +// Author: Derek Barnett + +#ifndef PBIBASICTYPES_H +#define PBIBASICTYPES_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include "pbbam/Compare.h" + +namespace PacBio { +namespace BAM { + +/// \brief The IndexResultBlock class represents a contiguous group of records +/// returned from a PBI lookup. +/// +/// Contiguous reads that satisfy a PBI lookup query will be merged down into a +/// single block. This helps to minimize the number of seeks in subsequent read +/// operations. +/// +/// An PBI-enabled reader or query can iterate over a list of IndexResultBlocks; +/// for each block, seeking to the first record and then sequentially reading +/// 'numReads' consecutive records before needing to seek again. +/// +struct PBBAM_EXPORT IndexResultBlock +{ +public: + IndexResultBlock(size_t idx, size_t numReads); + + IndexResultBlock() = default; + +public: + bool operator==(const IndexResultBlock& other) const; + bool operator!=(const IndexResultBlock& other) const; + +public: + size_t firstIndex_ = 0; ///< index of block's first record in BAM/PBI files (e.g. i-th record) + size_t numReads_ = 0; ///< number of reads in this block + int64_t virtualOffset_ = -1; ///< virtual offset of first record in this block +}; + +/// \brief container of PBI result blocks +/// +using IndexResultBlocks = std::deque; + +/// \brief container of raw PBI indices +/// +/// This is the primary result of PbiFilter -associated classes. This raw list +/// can participate in set operations (union, intersect) for compound filters, +/// and then be merged down into IndexResultBlocks for actual data file +/// random-access. +/// +using IndexList = std::vector; + +/// \brief pair representing a range of PBI indices: where interval +/// is [first, second) +/// +/// Used primarily by the PBI's CoordinateSortedData components. +/// +/// \sa PbiReferenceEntry, PbiRawReferenceData, & ReferenceLookupData +/// +using IndexRange = std::pair; + +} // namespace BAM +} // namespace PacBio + +#include "pbbam/internal/PbiBasicTypes.inl" + +#endif // PBIBASICTYPES_H diff --git a/include/pbbam/PbiBuilder.h b/include/pbbam/PbiBuilder.h new file mode 100644 index 0000000..6d8639f --- /dev/null +++ b/include/pbbam/PbiBuilder.h @@ -0,0 +1,179 @@ +// File Description +/// \file PbiBuilder.h +/// \brief Defines the PbiBuilder class. +// +// Author: Derek Barnett + +#ifndef PBIBUILDER_H +#define PBIBUILDER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +class BamRecord; +class PbiRawData; + +/// \brief The PbiBuilder class construct PBI index data from %BAM record data. +/// +/// Records are added one-by-one. This allows for either whole-file indexing of +/// existing %BAM files or for indexing "on-the-fly" alongside a %BAM file as it +/// is generated. +/// +/// For simple PBI creation from existing %BAM files, see PbiFile::CreateFrom. +/// This is the recommended approach, unless finer control or additional +/// processing is needed. +/// +class PBBAM_EXPORT PbiBuilder +{ +public: + /// \brief This enum allows you to control the compression level of the + /// output PBI file. + /// + /// Values are equivalent to zlib compression levels. See its documentation + /// for more details: http://www.zlib.net/manual.html + /// + enum CompressionLevel + { + CompressionLevel_0 = 0, + CompressionLevel_1 = 1, + CompressionLevel_2 = 2, + CompressionLevel_3 = 3, + CompressionLevel_4 = 4, + CompressionLevel_5 = 5, + CompressionLevel_6 = 6, + CompressionLevel_7 = 7, + CompressionLevel_8 = 8, + CompressionLevel_9 = 9, + + DefaultCompression = -1, + NoCompression = CompressionLevel_0, + FastCompression = CompressionLevel_1, + BestCompression = CompressionLevel_9 + }; + +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Initializes builder to write data to \p pbiFilename. + /// + /// \param[in] pbiFilename output filename + /// \param[in] compressionLevel zlib compression level + /// \param[in] numThreads number of threads for compression. If set to + /// 0, PbiBuilder will attempt to determine a + /// reasonable estimate. If set to 1, this will + /// force single-threaded execution. No checks + /// are made against an upper limit. + /// + /// \throws std::runtime_error if PBI file cannot be opened for writing + /// + PbiBuilder(const std::string& pbiFilename, + const PbiBuilder::CompressionLevel compressionLevel = PbiBuilder::DefaultCompression, + const size_t numThreads = 4); + + /// \brief Initializes builder to write data to \p pbiFilename. + /// + /// Reference data-tracking structures will be initialized to expect + /// \p numReferenceSequences. (This is useful so that we can mark any + /// references that lack observed data appropriately). + /// + /// \param[in] pbiFilename output filename + /// \param[in] numReferenceSequences number of possible reference + /// sequences, e.g. BamHeader::NumSequences + /// \param[in] compressionLevel zlib compression level + /// \param[in] numThreads number of threads for compression. If set to + /// 0, PbiBuilder will attempt to determine a + /// reasonable estimate. If set to 1, this will + /// force single-threaded execution. No checks + /// are made against an upper limit. + /// + /// \throws std::runtime_error if PBI file cannot be opened for writing + /// + PbiBuilder(const std::string& pbiFilename, const size_t numReferenceSequences, + const PbiBuilder::CompressionLevel compressionLevel = PbiBuilder::DefaultCompression, + const size_t numThreads = 4); + + /// \brief Initializes builder to write data to \p pbiFilename. + /// + /// Reference data-tracking structures will be initialized to expect + /// \p numReferenceSequences, but only if \p isCoordinateSorted is true. + /// + /// \param[in] pbiFilename output filename + /// \param[in] numReferenceSequences number of possible reference + /// sequences, e.g. BamHeader::NumSequences + /// \param[in] isCoordinateSorted if false, disables reference + /// sequence tracking + /// (BamHeader::SortOrder != "coordinate") + /// \param[in] compressionLevel zlib compression level + /// \param[in] numThreads number of threads for compression. If set to + /// 0, PbiBuilder will attempt to determine a + /// reasonable estimate. If set to 1, this will + /// force single-threaded execution. No checks + /// are made against an upper limit. + /// + /// \throws std::runtime_error if PBI file cannot be opened for writing + /// + PbiBuilder(const std::string& pbiFilename, const size_t numReferenceSequences, + const bool isCoordinateSorted, + const PbiBuilder::CompressionLevel compressionLevel = PbiBuilder::DefaultCompression, + const size_t numThreads = 4); + + /// \brief Destroys builder, writing its data out to PBI file. + /// + /// + /// \note Exceptions are swallowed. Use Close() if you want to catch them. + /// + ~PbiBuilder() noexcept; + + /// \} + +public: + /// \name Index Building + /// \{ + + /// \brief Adds \p record's data to underlying raw data structure. + /// + /// \note \p vOffset is a BGZF \b virtual offset into the %BAM file. To get + /// this value, you should use one of the following: \n + /// - while reading existing %BAM: BamReader::VirtualTell \n + /// - while writing new %BAM: BamWriter::Write(const BamRecord& record, int64_t* vOffset) \n + /// + /// + /// To build a PBI index while generating a %BAM file: + /// \include code/PbiBuilder_WithWriter.txt + /// + /// To build a PBI index from an existing %BAM file: + /// \include code/PbiBuilder_WithReader.txt + /// + /// \param[in] record input BamRecord to pull index data from + /// \param[in] vOffset \b virtual offset into %BAM file where record begins + /// + void AddRecord(const BamRecord& record, const int64_t vOffset); + + /// \brief Writes data out to PBI file & closes builder. + /// + /// \note Any exceptions are thrown to caller. If you don't care about + /// catching exceptions with file I/O, just let the builder go out of + /// scope and data will be written, but exceptions swallowed (to avoid + /// throwing from destructor). + /// + void Close(); + + /// \} + +private: + class PbiBuilderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PBIBUILDER_H diff --git a/include/pbbam/PbiFile.h b/include/pbbam/PbiFile.h new file mode 100644 index 0000000..c1f1fff --- /dev/null +++ b/include/pbbam/PbiFile.h @@ -0,0 +1,110 @@ +// File Description +/// \file PbiFile.h +/// \brief Defines the PbiFile enums, typedefs, and methods. +// +// Author: Derek Barnett + +#ifndef PBIFILE_H +#define PBIFILE_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/PbiBuilder.h" + +namespace PacBio { +namespace BAM { + +class BamFile; + +struct PbiFile +{ + + /// \brief This enum describes the PBI file sections + /// + enum Section + { + BASIC = 0x0000, ///< BasicData (required) + MAPPED = 0x0001, ///< MappedData (always optional) + REFERENCE = 0x0002, ///< ReferenceData (always optional) + BARCODE = 0x0004, ///< BarcodeData (always optional) + + ALL = BASIC | MAPPED | REFERENCE | BARCODE ///< Synonym for 'all sections' + }; + + /// \brief Helper typedef for storing multiple Section flags. + /// + using Sections = uint16_t; + + /// \brief This enum describes the PBI file version. + enum VersionEnum + { + Version_3_0_0 = 0x030000, ///< v3.0.0 + Version_3_0_1 = 0x030001, ///< v3.0.1 + Version_3_0_2 = 0x030002, ///< v3.0.2 + + CurrentVersion = Version_3_0_2 ///< Synonym for the current PBI version. + }; + + /// + /// \brief The BasicField enum + /// + enum class BasicField + { + RG_ID, + Q_START, + Q_END, + ZMW, + READ_QUALITY, + CONTEXT_FLAG, + VIRTUAL_OFFSET + }; + + /// + /// \brief The MappedField enum + /// + enum class MappedField + { + T_ID, + T_START, + T_END, + A_START, + A_END, + N_M, + N_MM, + N_INS, + N_DEL, + MAP_QUALITY, + STRAND + }; + + /// + /// \brief The BarcodeField enum + /// + enum class BarcodeField + { + BC_FORWARD, + BC_REVERSE, + BC_QUALITY + }; + + /// \brief Builds PBI index data from the supplied %BAM file and writes a + /// ".pbi" file. + /// + /// \param[in] bamFile source %BAM file + /// + /// \throws std::runtime_error if index file could not be created + /// + static void CreateFrom( + const BamFile& bamFile, + const PbiBuilder::CompressionLevel compressionLevel = PbiBuilder::DefaultCompression, + const size_t numThreads = 4); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PBIFILE_H diff --git a/include/pbbam/PbiFilter.h b/include/pbbam/PbiFilter.h new file mode 100644 index 0000000..16c337d --- /dev/null +++ b/include/pbbam/PbiFilter.h @@ -0,0 +1,250 @@ +// File Description +/// \file PbiFilter.h +/// \brief Defines the PbiFilter class & helper 'concept'. +// +// Author: Derek Barnett + +#ifndef PBIFILTER_H +#define PBIFILTER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include + +#include "pbbam/DataSet.h" +#include "pbbam/PbiBasicTypes.h" +#include "pbbam/PbiRawData.h" +#include "pbbam/Unused.h" + +namespace PacBio { +namespace BAM { + +namespace internal { +struct PbiFilterPrivate; +} + +/// \brief The PbiFilterConcept class provides compile-time enforcement of the +/// required interface for PbiFilter's child filters. +/// +template +struct PbiFilterConcept +{ + BOOST_CONCEPT_USAGE(PbiFilterConcept) + { + // All PBI filters (built-in or client-define) need only provide this + // interface: + // + // bool Accepts(const PbiRawData& index, const size_t row) const; + // + PbiRawData index; + auto result = filter.Accepts(index, 0); + UNUSED(result); + } + +private: + T filter; + // PbiRawData index; +}; + +/// \brief The PbiFilter class provides a mechanism for performing PBI-enabled +/// lookups. +/// +/// The PbiFilter API is designed to be flexible, both built-in and for +/// client-side customization. Built-in filters are provided for common queries, +/// and client code can define and use custom filters as well. More complex +/// filtering rules can be constructed via composition of simpler child filters. +/// +/// Filter objects used as children of PbiFilter need only provide a method that +/// matches this signature: +/// +/// \include code/PbiFilter_Interface.txt +/// +/// This requirement is enforced internally, using the PbiFilterConcept to +/// require a compatible interface without requiring inheritance. This approach +/// allows composition of heterogeneous filter types without worrying about a +/// class hierarchy, pointer ownership across library/client boundaries, etc. +/// +/// Thus a client application can define a custom filter if the built-in filters +/// do not quite meet requirements. This filter may then be used in further +/// PbiFilter composition, or directly to PbiFilterQuery +/// +/// \include code/PbiFilter_CustomFilter.txt +/// +/// As mentioned above, complex filters can be built up using multiple "child" +/// filters. These complex filters are constructed by using either +/// PbiFilter::Union (logical-OR over all direct children) or +/// PbiFilter::Intersection (logical-AND over direct children). +/// +/// \include code/PbiFilter_Composition.txt +/// +class PBBAM_EXPORT PbiFilter +{ +public: + enum CompositionType + { + INTERSECT, + UNION + }; + +public: + /// \name Set Operations + /// \{ + + /// \brief Creates a PbiFilter that acts as an intersection of the input + /// filters. + /// + /// A record must satisfy \b all of this filter's direct "child" filters. + /// + /// \param[in] filters vector of child filters + /// \returns composite filter + /// + static PbiFilter Intersection(std::vector filters); + + /// \brief Creates a PbiFilter that acts as a union of the input filters. + /// + /// A record must satisfy \b any of this filter's direct "child" filters. + /// + /// \param[in] filters vector of child filters + /// \returns composite filter + /// + static PbiFilter Union(std::vector filters); + + /// \} + +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates a PbiFilter from a %DataSet's described filters. + /// + /// A DataSet may contain a Filters element, itself a list of Filter + /// elements. Each Filter element will contain a Properties element, itself + /// a list of Property elements. + /// + /// The Filters hierarchy looks like this (in its XML output): + /// \verbinclude examples/plaintext/PbiFilter_DataSetXmlFilters.txt + /// + /// The resulting PbiFilter represents a union over all Filter elements, + /// with each Filter element requiring an intersection of all of its + /// Property criteria. These Property elements are mapped to built-in PBI + /// filter types. To use the labels in the example XML above, the filter + /// created here is equivalent to: + /// + /// (A && B) || (C && D) + /// + /// If a DataSet lacks any Filters, then an empty PbiFilter will be created + /// - corresponding to the dataset's entire contents. + /// + /// \param[in] dataset maybe containing filters + /// \returns composite filter + /// + static PbiFilter FromDataSet(const DataSet& dataset); + +public: + /// \brief Creates an empty filter. + /// + /// \note An empty filter will result in all records being returned, e.g. + /// for query iteration. + /// + /// \param[in] type composition type. Any additional child filters added to + /// this composite will be treated according to this type. + /// If INTERSECT, a record must match all child filters. If + /// UNION, a record must match any child filter. + /// + PbiFilter(const CompositionType type = INTERSECT); + + /// \brief Creates a composite filter (of INTERSECT type) with an initial + /// child filter. + /// + /// \note T must satisfy PbiFilterConcept + /// + /// \param[in] filter initial child filter + /// + template + PbiFilter(T filter); + + /// \brief Creates composite filter (of INTERSECT type) with a list of + /// initial child filters. + /// + /// \param[in] filters initial child filters + /// + PbiFilter(std::vector filters); + + PbiFilter(const PbiFilter&); + PbiFilter(PbiFilter&&) noexcept = default; + PbiFilter& operator=(const PbiFilter&); + PbiFilter& operator=(PbiFilter&&) noexcept = default; + + /// \} + +public: + /// \name Composition + /// \{ + + /// \brief Adds a new child filter of type T. + /// + /// \param[in] filter additional child filter. Type T must satisfy + /// PbiFilterConcept. + /// \returns reference to this filter + /// + template + PbiFilter& Add(T filter); + + /// \brief Adds a new child filter. + /// + /// \param[in] filter additional child filter + /// \returns reference to this filter + /// + PbiFilter& Add(PbiFilter filter); + + /// \brief Add child filters. + /// + /// \param[in] filters additional child filters + /// \returns reference to this filter + /// + PbiFilter& Add(std::vector filters); + + /// \returns true if this filter has no child filters. + bool IsEmpty() const; + + /// \returns number of child filters + size_t NumChildren() const; + + /// \returns filter type (intersect, union) + CompositionType Type() const; + + /// \} + +public: + /// \name Lookup + /// \{ + + /// \brief Performs the PBI index lookup, combining child results a + /// composite filter. + /// + /// \param[in] idx PBI (raw) index object + /// \param[in] row record number in %BAM/PBI files + /// + /// \returns true if record at \p row passes this filter criteria, + /// including children (if any) + /// + bool Accepts(const BAM::PbiRawData& idx, const size_t row) const; + + /// \} + +private: + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#include "pbbam/PbiFilterTypes.h" +#include "pbbam/internal/PbiFilter.inl" + +#endif // PBIFILTER_H diff --git a/include/pbbam/PbiFilterQuery.h b/include/pbbam/PbiFilterQuery.h new file mode 100644 index 0000000..5d2ca66 --- /dev/null +++ b/include/pbbam/PbiFilterQuery.h @@ -0,0 +1,80 @@ +// File Description +/// \file PbiFilterQuery.h +/// \brief Defines the PbiFilterQuery class. +// +// Author: Derek Barnett + +#ifndef PBIFILTERQUERY_H +#define PBIFILTERQUERY_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/PbiFilter.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The PbiFilter class provides iterable access to a DataSet's %BAM +/// records, limiting results to those matching filter criteria. +/// +/// Example: +/// \include code/PbiFilterQuery.txt +/// +/// \note Currently, all %BAM files must have a corresponding ".pbi" index file. +/// Use BamFile::EnsurePacBioIndexExists before creating the query if one +/// may not be present. +/// +class PBBAM_EXPORT PbiFilterQuery : public internal::IQuery +{ +public: + /// + /// \brief Creates a new PbiFilterQuery, limiting record results to only + /// those matching filter criteria defined in the DataSet XML. + /// + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or + /// PBI files. + /// + PbiFilterQuery(const DataSet& dataset); + + PbiFilterQuery(const DataSet& dataset, const PbiIndexCache& cache); + + /// \brief Creates a new PbiFilterQuery, limiting record results to only + /// those matching filter criteria + /// + /// \param[in] filter filtering criteria + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or + /// PBI files. + /// + PbiFilterQuery(const PbiFilter& filter, const DataSet& dataset); + + PbiFilterQuery(const PbiFilter& filter, const DataSet& dataset, const PbiIndexCache& cache); + + ~PbiFilterQuery() override; + + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(BamRecord& r) override; + + /// \brief Return number of records that pass the provided filter + /// + uint32_t NumReads() const; + +private: + class PbiFilterQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PBIFILTERQUERY_H diff --git a/include/pbbam/PbiFilterTypes.h b/include/pbbam/PbiFilterTypes.h new file mode 100644 index 0000000..1ea0bfa --- /dev/null +++ b/include/pbbam/PbiFilterTypes.h @@ -0,0 +1,929 @@ +// File Description +/// \file PbiFilterTypes.h +/// \brief Defines the built-in PBI filters. +// +// Author: Derek Barnett + +#ifndef PBIFILTERTYPES_H +#define PBIFILTERTYPES_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include + +#include "pbbam/Compare.h" +#include "pbbam/PbiFile.h" +#include "pbbam/PbiFilter.h" + +namespace PacBio { +namespace BAM { + +namespace internal { + +/// \internal +/// +/// Provides basic container for value/compare-type pair +/// +template +class FilterBase +{ +public: + T value_; + boost::optional> multiValue_; + Compare::Type cmp_; + +protected: + FilterBase(T value, const Compare::Type cmp); + FilterBase(std::vector values, const Compare::Type cmp = Compare::CONTAINS); + + bool CompareHelper(const T& lhs) const; + +private: + bool CompareSingleHelper(const T& lhs) const; + bool CompareMultiHelper(const T& lhs) const; +}; + +/// \internal +/// +/// Dispatches the lookup to BarcodeLookupData +/// +template +class BarcodeDataFilterBase : public FilterBase +{ +public: + bool Accepts(const PbiRawData& idx, const size_t row) const; + +protected: + BarcodeDataFilterBase(T value, const Compare::Type cmp); + BarcodeDataFilterBase(std::vector values, const Compare::Type cmp = Compare::CONTAINS); +}; + +/// \internal +/// +/// Dispatches the lookup to BasicLookupData +/// +template +class BasicDataFilterBase : public FilterBase +{ +public: + bool Accepts(const PbiRawData& idx, const size_t row) const; + +protected: + BasicDataFilterBase(T value, const Compare::Type cmp); + BasicDataFilterBase(std::vector values, const Compare::Type cmp = Compare::CONTAINS); +}; + +/// \internal +/// +/// Dispatches the lookup to MappedLookupData +/// +template +class MappedDataFilterBase : public FilterBase +{ +public: + bool Accepts(const PbiRawData& idx, const size_t row) const; + +protected: + MappedDataFilterBase(T value, const Compare::Type cmp); + MappedDataFilterBase(std::vector values, const Compare::Type cmp = Compare::CONTAINS); +}; + +} // namespace internal + +/// \brief The PbiAlignedEndFilter class provides a PbiFilter-compatible filter +/// on aligned end. +/// +/// Example: \include code/PbiAlignedEndFilter.txt +/// +/// \sa BamRecord::AlignedEnd +/// +class PbiAlignedEndFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a filter on aligned end. + /// + /// \param[in] position value to compare on + /// \param[in] cmp compare type + /// + PbiAlignedEndFilter(const uint32_t position, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiAlignedLengthFilter class provides a PbiFilter-compatible +/// filter on aligned length. +/// +/// Example: \include code/PbiAlignedLengthFilter.txt +/// +/// \sa BamRecord::AlignedEnd, BamRecord::AlignedStart +/// +class PbiAlignedLengthFilter : public internal::FilterBase +{ +public: + /// \brief Creates a filter on aligned length. + /// + /// \param[in] length value to compare on + /// \param[in] cmp compare type + /// + PbiAlignedLengthFilter(const uint32_t length, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; +}; + +/// \brief The PbiAlignedStartFilter class provides a PbiFilter-compatible +/// filter on aligned start. +/// +/// Example: \include code/PbiAlignedStartFilter.txt +/// +/// \sa BamRecord::AlignedStart +/// +class PbiAlignedStartFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a filter on aligned start. + /// + /// \param[in] position value to compare on + /// \param[in] cmp compare type + /// + PbiAlignedStartFilter(const uint32_t position, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiAlignedStrandFilter class provides a PbiFilter-compatible +/// filter on aligned strand. +/// +/// Example: \include code/PbiAlignedStrandFilter.txt +/// +/// \sa BamRecord::AlignedStrand +/// +class PbiAlignedStrandFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a strand filter. + /// + /// \param[in] strand strand value to compare on + /// \param[in] cmp compare type + /// + PbiAlignedStrandFilter(const Strand strand, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiBarcodeFilter class provides a PbiFilter-compatible filter on +/// barcode ID. +/// +/// Any record with this barcode ID (forward or reverse) will pass this filter. +/// +/// Example: \include code/PbiBarcodeFilter.txt +/// +/// \sa BamRecord::BarcodeForward, BamRecord::BarcodeReverse +/// +class PbiBarcodeFilter +{ +public: + /// \brief Creates a single-value barcode filter. + /// + /// \param[in] barcode barcode ID to compare on + /// \param[in] cmp compare type + /// + PbiBarcodeFilter(const int16_t barcode, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted barcode filter. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no barcodes in the blacklist. + /// + /// \param[in] barcodes barcode IDs + /// \param[in] cmp compare type + /// + PbiBarcodeFilter(std::vector barcodes, const Compare::Type cmp = Compare::CONTAINS); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; + +private: + PbiFilter compositeFilter_; +}; + +/// \brief The PbiBarcodeForwardFilter class provides a PbiFilter-compatible +/// filter on forward barcode ID. +/// +/// Example: \include code/PbiBarcodeForwardFilter.txt +/// +/// \sa BamRecord::BarcodeForward +/// +class PbiBarcodeForwardFilter + : public internal::BarcodeDataFilterBase +{ +public: + /// \brief Creates a single-value forward barcode filter. + /// + /// \param[in] bcFwdId (forward) barcode ID to compare on + /// \param[in] cmp compare type + /// + PbiBarcodeForwardFilter(const int16_t bcFwdId, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted forward barcode filter. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] barcodes barcode IDs + /// \param[in] cmp compare type + /// + PbiBarcodeForwardFilter(std::vector barcodes, + const Compare::Type cmp = Compare::CONTAINS); +}; + +/// \brief The PbiBarcodeQualityFilter class provides a PbiFilter-compatible +/// filter on barcode quality. +/// +/// Example: \include code/PbiBarcodeQualityFilter.txt +/// +/// \sa BamRecord::BarcodeQuality +/// +class PbiBarcodeQualityFilter + : public internal::BarcodeDataFilterBase +{ +public: + /// \brief Creates a single-value barcode quality filter. + /// + /// \param[in] bcQuality barcode quality to compare on + /// \param[in] cmp compare type + /// + PbiBarcodeQualityFilter(const uint8_t bcQuality, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiBarcodeReverseFilter class provides a PbiFilter-compatible +/// filter on forward barcode ID. +/// +/// Example: \include code/PbiBarcodeReverseFilter.txt +/// +/// \sa BamRecord::BarcodeReverse +/// +class PbiBarcodeReverseFilter + : public internal::BarcodeDataFilterBase +{ +public: + /// \brief Creates a single-value reverse barcode filter. + /// + /// \param[in] bcRevId (reverse) barcode ID to compare on + /// \param[in] cmp compare type + /// + PbiBarcodeReverseFilter(const int16_t bcRevId, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted reverse barcode filter. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] barcodes barcode IDs + /// \param[in] cmp compare type + /// + PbiBarcodeReverseFilter(std::vector barcodes, + const Compare::Type cmp = Compare::CONTAINS); +}; + +/// \brief The PbiBarcodesFilter class provides a PbiFilter-compatible filter on +/// both forward & reverse barcode IDs. +/// +/// A record must match both IDs to pass the filter. +/// +/// Example: \include code/PbiBarcodesFilter.txt +/// +/// \sa BamRecord::Barcodes +/// +class PbiBarcodesFilter +{ +public: + /// \brief Creates a barcodes filter from a std::pair of IDs. + /// + /// pair.first -> BarcodeForward\n + /// pair.second -> BarcodeReverse + /// + /// \param[in] barcodes barcode IDs to compare on + /// \param[in] cmp compare type + /// + PbiBarcodesFilter(const std::pair barcodes, + const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a barcodes filter from forward & reverse IDs. + /// + /// \param[in] bcForward forward barcode ID to compare on + /// \param[in] bcReverse reverse barcode ID to compare on + /// \param[in] cmp compare type + /// + PbiBarcodesFilter(const int16_t bcForward, const int16_t bcReverse, + const Compare::Type cmp = Compare::EQUAL); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; + +private: + PbiFilter compositeFilter_; +}; + +/// \brief The PbiIdentityFilter class provides a PbiFilter-compatible filter on +/// read identity (% aligned match). +/// +/// Read identity is equivalent to: 1.0 - (nMM + nDel + nIns)/readLength. +/// +/// Example: \include code/PbiIdentityFilter.txt +/// +class PbiIdentityFilter : public internal::FilterBase +{ +public: + /// \brief Creates a read identity filter. + /// + /// \param[in] identity value to compare on + /// \param[in] cmp compare type + /// + PbiIdentityFilter(const float identity, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; +}; + +/// \brief The PbiLocalContextFilter class provides a PbiFilter-compatible +/// filter on local context (adapter, barcode, etc.). +/// +/// The primary Compare::Type operators intended for this filter are: +/// Compare::EQUAL, Compare::NOT_EQUAL, Compare::CONTAINS, and +/// Compare::NOT_CONTAINS. +/// +/// Example: \include code/PbiLocalContextFilter.txt +/// +class PbiLocalContextFilter + : public internal::BasicDataFilterBase +{ +public: + PbiLocalContextFilter(const LocalContextFlags& flags, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiMapQualityFilter class provides a PbiFilter-compatible filter on +/// mapping quality. +/// +/// Example: \include code/PbiMapQualityFilter.txt +/// +/// \sa BamRecord::MapQuality +/// +class PbiMapQualityFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a map quality filter. + /// + /// \param[in] mapQual value to compare on + /// \param[in] cmp compare type + /// + PbiMapQualityFilter(const uint8_t mapQual, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiMovieNameFilter class provides a PbiFilter-compatible filter +/// on movie name. +/// +/// Example: \include code/PbiMovieNameFilter.txt +/// +/// \sa BamRecord::MovieName +/// +class PbiMovieNameFilter +{ +public: + /// \brief Creates a single-value movie name filter. + /// + /// \param[in] movieName movie name to compare on + /// + /// \note There is no compare type parameter here, it is always + /// Compare::EQUAL. Records will match movie name, exactly. + /// + PbiMovieNameFilter(const std::string& movieName, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted movie name filter. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] movieNames movie names + /// \param[in] cmp compare type + /// + PbiMovieNameFilter(const std::vector& movieNames, + const Compare::Type cmp = Compare::CONTAINS); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; + +private: + PbiFilter compositeFilter_; + Compare::Type cmp_; +}; + +/// \brief The PbiNumDeletedBasesFilter class provides a PbiFilter-compatible +/// filter on the number of deleted bases. +/// +/// Example: \include code/PbiNumDeletedBasesFilter.txt +/// +/// \sa BamRecord::NumDeletedBases +/// +class PbiNumDeletedBasesFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a filter on the number of deleted bases. + /// + /// \param[in] numDeletions value to compare on + /// \param[in] cmp compare type + /// + PbiNumDeletedBasesFilter(const size_t numDeletions, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiNumInsertededBasesFilter class provides a PbiFilter-compatible +/// filter on the number of inserted bases. +/// +/// Example: \include code/PbiNumInsertedBasesFilter.txt +/// +/// \sa BamRecord::NumInsertedBases +/// +class PbiNumInsertedBasesFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a filter on the number of inserted bases. + /// + /// \param[in] numInsertions value to compare on + /// \param[in] cmp compare type + /// + PbiNumInsertedBasesFilter(const size_t numInsertions, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiNumMatchesFilter class provides a PbiFilter-compatible filter +/// on the number of matched bases. +/// +/// Example: \include code/PbiNumMatchesFilter.txt +/// +/// \sa BamRecord::NumMatches +/// +class PbiNumMatchesFilter : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a filter on the number of matched bases. + /// + /// \param[in] numMatchedBases value to compare on + /// \param[in] cmp compare type + /// + PbiNumMatchesFilter(const size_t numMatchedBases, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiNumMismatchesFilter class provides a PbiFilter-compatible +/// filter on the number of mismatched bases. +/// +/// Example: \include code/PbiNumMismatchesFilter.txt +/// +/// \sa BamRecord::NumMismatches +/// +class PbiNumMismatchesFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a filter on the number of mismatched bases. + /// + /// \param[in] numMismatchedBases value to compare on + /// \param[in] cmp compare type + /// + PbiNumMismatchesFilter(const size_t numMismatchedBases, + const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiQueryEndFilter class provides a PbiFilter-compatible filter +/// on query end. +/// +/// Example: \include code/PbiQueryEndFilter.txt +/// +/// \sa BamRecord::QueryEnd +/// +class PbiQueryEndFilter : public internal::BasicDataFilterBase +{ +public: + /// \brief Creates a filter on query end position. + /// + /// \param[in] position value to compare on + /// \param[in] cmp compare type + /// + PbiQueryEndFilter(const int32_t position, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiQueryLengthFilter class provides a PbiFilter-compatible filter +/// on query length. +/// +/// queryLength = (queryEnd - queryStart) +/// +/// Example: \include code/PbiQueryLengthFilter.txt +/// +/// \sa BamRecord::QueryEnd, BamRecord::QueryStart +/// +class PbiQueryLengthFilter : public internal::FilterBase +{ +public: + /// \brief Creates a filter on query length + /// + /// \param[in] length value to compare on + /// \param[in] cmp compare type + /// + PbiQueryLengthFilter(const int32_t length, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; +}; + +/// \brief The PbiQueryNameFilter class provides a PbiFilter-compatible filter +/// on name length. +/// +/// Example: \include code/PbiQueryNameFilter.txt +/// +/// \sa BamRecord::FullName +/// +class PbiQueryNameFilter +{ +public: + /// \brief Creates a single-value query name filter. + /// + /// \param[in] qname query name to compare on + /// + /// \note There is no compare type parameter here, it is always + /// Compare::EQUAL. Records will match query name, exactly. + /// + PbiQueryNameFilter(const std::string& qname, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted query name filter. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] queryNames query names + /// \param[in] cmp compare type + /// + PbiQueryNameFilter(const std::vector& queryNames, + const Compare::Type cmp = Compare::CONTAINS); + + PbiQueryNameFilter(const PbiQueryNameFilter& other); + ~PbiQueryNameFilter(); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; + +private: + struct PbiQueryNameFilterPrivate; + std::unique_ptr d_; +}; + +/// \brief The PbiQueryStartFilter class provides a PbiFilter-compatible filter +/// on query start. +/// +/// Example: \include code/PbiQueryStartFilter.txt +/// +/// \sa BamRecord::QueryStart +/// +class PbiQueryStartFilter + : public internal::BasicDataFilterBase +{ +public: + /// \brief Creates a filter on query start position. + /// + /// \param[in] position value to compare on + /// \param[in] cmp compare type + /// + PbiQueryStartFilter(const int32_t position, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiReadAccuracyFilter class provides a PbiFilter-compatible filter +/// on read accuracy. +/// +/// Example: \include code/PbiReadAccuracyFilter.txt +/// +/// \sa BamRecord::ReadAccuracy +/// +class PbiReadAccuracyFilter + : public internal::BasicDataFilterBase +{ +public: + /// \brief Creates a filter on read accuracy. + /// + /// \param[in] accuracy value to compare on + /// \param[in] cmp compare type + /// + PbiReadAccuracyFilter(const Accuracy accuracy, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiReadGroupFilter class provides a PbiFilter-compatible filter +/// on read group. +/// +/// Example: \include code/PbiReadGroupFilter.txt +/// +/// \sa BamRecord::ReadGroup, +/// BamRecord::ReadGroupId, +/// BamRecord::ReadGroupNumericId +/// +class PbiReadGroupFilter +{ +public: + /// \brief Creates a filter on read group (numeric) ID value + /// + /// \param[in] rgId numeric read group ID + /// \param[in] cmp compare type + /// + /// \sa BamRecord::ReadGroupNumericId + /// + PbiReadGroupFilter(const int32_t rgId, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a filter on printable read group ID value + /// + /// \param[in] rgId read group ID string + /// \param[in] cmp compare type + /// + /// \sa BamRecord::ReadGroupId + /// + PbiReadGroupFilter(const std::string& rgId, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a filter on read group (object). + /// + /// \param[in] rg read group object + /// \param[in] cmp compare type + /// + /// \sa BamRecord::ReadGroup + /// + PbiReadGroupFilter(const ReadGroupInfo& rg, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted filter on read group numeric IDs. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] rgIds numeric read group IDs + /// \param[in] cmp compare type + /// + PbiReadGroupFilter(const std::vector& rgIds, + const Compare::Type cmp = Compare::CONTAINS); + + /// \brief Creates a whitelisted or blacklisted filter on read group string IDs. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] rgIds read group ID strings + /// \param[in] cmp compare type + /// + PbiReadGroupFilter(const std::vector& rgIds, + const Compare::Type cmp = Compare::CONTAINS); + + /// \brief Creates a whitelisted or blacklisted filter on read group objects. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] readGroups ReadGroupInfo objects + /// \param[in] cmp compare type + /// + PbiReadGroupFilter(const std::vector& readGroups, + const Compare::Type cmp = Compare::EQUAL); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; + +private: + // RGID number => barcode(s) filter + std::unordered_map>>> lookup_; + Compare::Type cmp_; +}; + +/// \brief The PbiReferenceEndFilter class provides a PbiFilter-compatible +/// filter on reference end. +/// +/// Example: \include code/PbiReferenceEndFilter.txt +/// +/// \sa BamRecord::ReferenceEnd +/// +class PbiReferenceEndFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a filter on reference end. + /// + /// \param[in] tEnd value to compare on + /// \param[in] cmp compare type + /// + PbiReferenceEndFilter(const uint32_t tEnd, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiReferenceIdFilter class provides a PbiFilter-compatible +/// filter on reference ID. +/// +/// Example: \include code/PbiReferenceIdFilter.txt +/// +/// \sa BamRecord::ReferenceId +/// +class PbiReferenceIdFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a single-value reference ID filter. + /// + /// \param[in] tId reference ID to compare on + /// \param[in] cmp compare type + /// + PbiReferenceIdFilter(const int32_t tId, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted reference ID filter. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] tIds reference IDs + /// \param[in] cmp compare type + /// + PbiReferenceIdFilter(std::vector tIds, const Compare::Type cmp = Compare::CONTAINS); +}; + +/// \brief The PbiReferenceNameFilter class provides a PbiFilter-compatible +/// filter on reference name. +/// +/// Example: \include code/PbiReferenceNameFilter.txt +/// +/// \sa BamRecord::ReferenceName +/// +class PbiReferenceNameFilter +{ +public: + /// \brief Creates a single-value reference name filter. + /// + /// \param[in] rname reference ID to compare on + /// \param[in] cmp compare type + /// + PbiReferenceNameFilter(std::string rname, Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted reference name filter. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] rnames reference names + /// \param[in] cmp compare type + /// + PbiReferenceNameFilter(std::vector rnames, + const Compare::Type cmp = Compare::CONTAINS); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; + +private: + mutable bool initialized_ = false; + mutable PbiFilter subFilter_; + std::string rname_; + boost::optional> rnameWhitelist_; + Compare::Type cmp_; + + // marked const so we can delay setup of filter in Accepts(), once we have + // access to PBI/BAM input. modified values marked mutable accordingly + void Initialize(const PbiRawData& idx) const; + + void Validate() const; +}; + +/// \brief The PbiReferenceStartFilter class provides a PbiFilter-compatible +/// filter on reference start. +/// +/// Example: \include code/PbiReferenceStartFilter.txt +/// +/// \sa BamRecord::ReferenceStart +/// +class PbiReferenceStartFilter + : public internal::MappedDataFilterBase +{ +public: + /// \brief Creates a filter on reference start. + /// + /// \param[in] tStart value to compare on + /// \param[in] cmp compare type + /// + PbiReferenceStartFilter(const uint32_t tStart, const Compare::Type cmp = Compare::EQUAL); +}; + +/// \brief The PbiZmwFilter class provides a PbiFilter-compatible filter on +/// ZMW hole number. +/// +/// Example: \include code/PbiZmwFilter.txt +/// +/// \sa BamRecord::HoleNumber +/// +class PbiZmwFilter : public internal::BasicDataFilterBase +{ +public: + /// \brief Creates a single-value ZMW hole number filter. + /// + /// \param[in] zmw value to compare on + /// \param[in] cmp compare type + /// + PbiZmwFilter(const int32_t zmw, const Compare::Type cmp = Compare::EQUAL); + + /// \brief Creates a whitelisted or blacklisted ZMW hole number filter. + /// + /// \note If compare type is Compare::CONTAINS, accepted records will match + /// at least one value from whitelist, in bc_forward. + /// If compare type is Compare::NOT_CONTAINS, accepted records will + /// match no values in the blacklist. + /// + /// \param[in] zmws ZMW hole numbers + /// \param[in] cmp compare type + /// + PbiZmwFilter(std::vector zmws, const Compare::Type cmp = Compare::CONTAINS); +}; + +// ---------------------------------------------- +// NOTE: modulo filtering only enabled for ZMW. +// +// I need to generalize more if we're going to use +// this on more fields. +// ---------------------------------------------- + +enum class FilterHash +{ + UNSIGNED_LONG_CAST, + BOOST_HASH_COMBINE, +}; + +class PbiZmwModuloFilter +{ +public: + PbiZmwModuloFilter(const uint32_t denominator, const uint32_t value, + const FilterHash hashtype = FilterHash::UNSIGNED_LONG_CAST, + const Compare::Type = Compare::EQUAL); + + /// \brief Performs the actual index lookup. + /// + /// Most client code should not need to use this method directly. + /// + bool Accepts(const PbiRawData& idx, const size_t row) const; + +private: + uint32_t denominator_; + uint32_t value_; + FilterHash hash_; + Compare::Type cmp_; +}; + +} // namespace BAM +} // namespace PacBio + +#include "pbbam/internal/PbiFilterTypes.inl" + +#endif // PBIFILTERTYPES_H diff --git a/include/pbbam/PbiIndexedBamReader.h b/include/pbbam/PbiIndexedBamReader.h new file mode 100644 index 0000000..1dd8557 --- /dev/null +++ b/include/pbbam/PbiIndexedBamReader.h @@ -0,0 +1,124 @@ +// File Description +/// \file PbiIndexedBamReader.h +/// \brief Defines the PbiIndexedBamReader class. +// +// Author: Derek Barnett + +#ifndef PBIINDEXEDBAMREADER_H +#define PBIINDEXEDBAMREADER_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/BamFile.h" +#include "pbbam/BamReader.h" +#include "pbbam/PbiBasicTypes.h" +#include "pbbam/PbiFilter.h" + +namespace PacBio { +namespace BAM { + +/// \brief The PbiIndexedBamReader class provides read-only iteration over %BAM +/// records, limited to some filtering criteria. +/// +/// The PacBio BAM index (*.pbi) is used to allow random-access operations. +/// +class PBBAM_EXPORT PbiIndexedBamReader : public BamReader +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Constructs %BAM reader, with an initial filter. + /// + /// All reads that satisfy the filter will be available. + /// + /// \param[in] filter PbiFilter or compatible object + /// \param[in] bamFilename input %BAM filename + /// + /// \throws std::runtime_error if either file (*.bam or *.pbi) cannot be + /// read + /// + PbiIndexedBamReader(PbiFilter filter, const std::string& bamFilename); + PbiIndexedBamReader(PbiFilter filter, const std::string& bamFilename, + const std::shared_ptr& index); + + /// \brief Constructs %BAM reader, with an initial filter. + /// + /// All reads that satisfy the filter will be available. + /// + /// \param[in] filter PbiFilter or compatible object + /// \param[in] bamFile input BamFile object + /// + /// \throws std::runtime_error if either file (*.bam or *.pbi) cannot be + /// read + /// + PbiIndexedBamReader(PbiFilter filter, BamFile bamFile); + PbiIndexedBamReader(PbiFilter filter, BamFile bamFile, + const std::shared_ptr& index); + + /// \brief Constructs %BAM reader, with no initial filter. + /// + /// Useful for delaying either specifying the filtering criteria or + /// performing the PBI lookups. + /// + /// \param[in] bamFilename input %BAM filename + /// + /// \throws std::runtime_error if either file (*.bam or *.pbi) cannot be + /// read + /// + PbiIndexedBamReader(const std::string& bamFilename); + PbiIndexedBamReader(const std::string& bamFilename, const std::shared_ptr& index); + + /// \brief Constructs %BAM reader, with no initial filter. + /// + /// Useful for delaying either specifying the filtering criteria or + /// performing the PBI lookups. + /// + /// \param[in] bamFile input BamFile object + /// + /// \throws std::runtime_error if either file (*.bam or *.pbi) cannot be + /// read + /// + PbiIndexedBamReader(BamFile bamFile); + PbiIndexedBamReader(BamFile bamFile, const std::shared_ptr& index); + + ~PbiIndexedBamReader() override; + + /// \} + + /// \name Filtering & Index Data + /// \{ + + const BamFile& File() const; + + /// \returns the current filter active on this reader + const PbiFilter& Filter() const; + + uint32_t NumReads() const; + + /// \brief Sets a new filter on the reader. + /// + /// \param[in] filter + /// \returns reference to this reader + /// + PbiIndexedBamReader& Filter(PbiFilter filter); + + /// \return list of index blocks (chunks of passing reads) currently in use + const IndexResultBlocks& IndexBlocks() const; + + /// \} + +protected: + int ReadRawData(BGZF* bgzf, bam1_t* b) override; + +private: + class PbiIndexedBamReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PBIINDEXEDBAMREADER_H diff --git a/include/pbbam/PbiRawData.h b/include/pbbam/PbiRawData.h new file mode 100644 index 0000000..e602e50 --- /dev/null +++ b/include/pbbam/PbiRawData.h @@ -0,0 +1,465 @@ +// File Description +/// \file PbiRawData.h +/// \brief Defines the classes used for working with raw PBI data. +// +// Author: Derek Barnett + +#ifndef PBIRAWDATA_H +#define PBIRAWDATA_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include "pbbam/PbiFile.h" + +namespace PacBio { +namespace BAM { + +class BamFile; +class BamRecord; +class DataSet; + +/// \brief The PbiRawBarcodeData class represents the raw data stored in the +/// "BarcodeData" section of the PBI index. +/// +class PBBAM_EXPORT PbiRawBarcodeData +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates an empty data structure, preallocating space for a known + /// number of records. + PbiRawBarcodeData(uint32_t numReads); + + PbiRawBarcodeData() = default; + + /// \} + +public: + /// \name Index Construction + /// \{ + + /// \brief Adds a record's barcode data. + /// + /// \param[in] b %BAM record + /// + void AddRecord(const BamRecord& b); + + /// \} + +public: + /// \name Raw Data Containers + /// \{ + + std::vector bcForward_; + std::vector bcReverse_; + std::vector bcQual_; + + /// \} +}; + +/// \brief The PbiRawMappedData class represents the raw data stored in the +/// "MappedData" section of the PBI index. +/// +class PBBAM_EXPORT PbiRawMappedData +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates an empty data structure, preallocating space for a known + /// number of records. + PbiRawMappedData(uint32_t numReads); + + PbiRawMappedData() = default; + + /// \} + +public: + /// \name Index Construction + /// \{ + + /// \brief Adds a record's mapping data. + /// + /// \param[in] b %BAM record + /// + void AddRecord(const BamRecord& b); + + /// \} + +public: + /// \name Index Data Query + /// \{ + + /// \brief Calculates the number of deleted bases for a particular record. + /// + /// Convenvience method. Equivalent to: + /// \code{.cpp} + /// NumDeletedAndInsertedBasesAt(i).first; + /// \endcode + /// + /// \param[in] recordIndex i-th record + /// \returns number of deleted bases + /// + uint32_t NumDeletedBasesAt(size_t recordIndex) const; + + /// \brief Calculates the number of inserted bases for a particular record. + /// + /// Convenvience method. Equivalent to: + /// \code{.cpp} + /// NumDeletedAndInsertedBasesAt(i).second; + /// \endcode + /// + /// \param[in] recordIndex i-th record + /// \returns number of inserted bases + /// + uint32_t NumInsertedBasesAt(size_t recordIndex) const; + + /// \brief Calculates the number of deleted & inserted bases for a + /// particular record. + /// + /// \param[in] recordIndex i-th record in the data set + /// \returns a pair consisting of (numDeletions,numInsertions) + /// + std::pair NumDeletedAndInsertedBasesAt(size_t recordIndex) const; + + /// \} + +public: + /// \name Raw Data Containers + /// \{ + + std::vector tId_; + std::vector tStart_; + std::vector tEnd_; + std::vector aStart_; + std::vector aEnd_; + std::vector revStrand_; + std::vector nM_; + std::vector nMM_; + std::vector mapQV_; + + /// \} +}; + +/// \brief The PbiReferenceEntryClass represents a single reference in the PBI +/// CoordinateSorted section. +/// +/// A reference entry consists of an associated reference ID (tId), as well as +/// start and end indices into the %BAM or PBI. +/// +/// \note Rows are given in the interval [start, end). +/// +class PBBAM_EXPORT PbiReferenceEntry +{ +public: + using ID = uint32_t; + using Row = uint32_t; + +public: + static const ID UNMAPPED_ID; + static const Row UNSET_ROW; + +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates a default entry. + /// + /// - default ID: PbiReferenceEntry::UNMAPPED_ID \n + /// - default rows: PbiReferenceEntry::UNSET_ROW + /// + PbiReferenceEntry(); + + /// \brief Creates a reference entry, with no rows set. + /// + /// - default rows: PbiReferenceEntry::UNSET_ROW + /// + PbiReferenceEntry(ID id); + + /// \brief Creates a reference entry, with rows set. + /// + PbiReferenceEntry(ID id, Row beginRow, Row endRow); + + bool operator==(const PbiReferenceEntry& other) const; + + /// \} + +public: + /// \name Reference Data Members + /// \{ + + ID tId_; + Row beginRow_; + Row endRow_; + + /// \} +}; + +/// \brief The PbiRawReferenceData class represents the raw data stored in the +/// "CoordinateSortedData" section of the PBI index. +/// +class PBBAM_EXPORT PbiRawReferenceData +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates an empty data structure, preallocating space for a + /// number of references. + /// + /// This constructor is recommended as this is the safest way to ensure that + /// references without observed mappings are included in the final output. + /// + PbiRawReferenceData(uint32_t numRefs); + + PbiRawReferenceData() = default; + + /// \} + +public: + /// \name Raw Data Containers + /// \{ + + std::vector entries_; + + /// \} +}; + +/// \brief The PbiRawBasicData class represents the raw data stored in the +/// "BasicData" section of the PBI index. +/// +class PBBAM_EXPORT PbiRawBasicData +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates an empty data structure, preallocating space for a known + /// number of records. + PbiRawBasicData(uint32_t numReads); + + PbiRawBasicData() = default; + + /// \} + +public: + /// \name Index Construction + /// \{ + + /// \brief Adds a record's mapping data. + /// + /// \param[in] b %BAM record + /// \param[in] offset \b virtual file offset where record begins + /// + void AddRecord(const BamRecord& b, int64_t offset); + + /// \} + +public: + /// \name Raw Data Containers + /// \{ + + std::vector rgId_; + std::vector qStart_; + std::vector qEnd_; + std::vector holeNumber_; + std::vector readQual_; + std::vector ctxtFlag_; + std::vector fileOffset_; + std::vector fileNumber_; + + /// \} +}; + +/// \brief The PbiRawData class provides an representation of raw PBI index +/// data, used mostly for construction or I/O. +/// +/// The PbiRawData class itself provides access to a few high-level attributes +/// (e.g. version, number of records, etc.). The actual index data is stored +/// in its member components: +/// PbiRawBasicData, +/// PbiRawMappedData, +/// PbiRawReferenceData, & +/// PbiRawBarcodeData . +/// +class PBBAM_EXPORT PbiRawData +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Loads raw PBI data from a file. + /// + /// \param[in] pbiFilename ".pbi" filename + /// + /// \throws std::runtime_error if file contents cannot be loaded properly + /// + PbiRawData(std::string pbiFilename); + + /// \brief Loads a raw, aggregate PBI data from a dataset + /// + /// This constructor creates a raw index object that contains an aggregation + /// of index data across the dataset. + /// + /// \note ReferenceData (the per-reference table for coordinate-sorted data) + /// is not currently available for the index aggregate. All other + /// per-record data sections will be present. + /// + /// \param[in] dataset DataSet object + /// + /// \throws std::runtime_error if file(s) contents cannot be loaded properly + /// + explicit PbiRawData(const DataSet& dataset); + + PbiRawData() = default; + + /// \} + +public: + /// \name PBI General Attributes + /// \{ + + /// \returns true if index has BarcodeData section + bool HasBarcodeData() const; + + /// \returns true if index has MappedData section + bool HasMappedData() const; + + /// \returns true if index has ReferenceData section + bool HasReferenceData() const; + + /// \returns true if index has \b section + /// \param[in] section PbiFile::Section identifier + /// + bool HasSection(const PbiFile::Section section) const; + + /// \returns index filename ("*.pbi") + /// + /// \note Returns an empty string if the underlying data was calculated in + /// code or aggregated from a DataSet, rather than loaded from a + /// single PBI file. + /// + std::string Filename() const; + + /// \returns enum flags representing the file sections present + PbiFile::Sections FileSections() const; + + /// \returns the number of records in the PBI(s) + uint32_t NumReads() const; + + /// \returns the PBI file's version + PbiFile::VersionEnum Version() const; + + /// \} + +public: + /// \name Raw Data Components + /// \{ + + /// \returns const reference to BarcodeData lookup structure + /// + /// May be empty, check result of HasBarcodeData. + /// + const PbiRawBarcodeData& BarcodeData() const; + + /// \returns const reference to BasicData lookup structure + const PbiRawBasicData& BasicData() const; + + /// \returns const reference to MappedData lookup structure + /// + /// May be empty, check result of HasMappedData. + /// + const PbiRawMappedData& MappedData() const; + + /// \returns const reference to reference data lookup structure + /// + /// May be empty, check result of HasReferenceData. + /// + const PbiRawReferenceData& ReferenceData() const; + + /// \} + +public: + /// \name PBI General Attributes + /// \{ + + /// \brief Sets the file section flags. + /// + /// \param[in] sections section flags + /// \returns reference to this index + /// + PbiRawData& FileSections(PbiFile::Sections sections); + + /// \brief Sets the number of indexed records. + /// + /// \param[in] num number of records + /// \returns reference to this index + /// + PbiRawData& NumReads(uint32_t num); + + /// \brief Sets PBI file version. + /// + /// \param[in] version file version + /// \returns reference to this index + /// + PbiRawData& Version(PbiFile::VersionEnum version); + + /// \} + +public: + /// \name Raw Data Components + /// \{ + + /// \returns reference to BarcodeData lookup structure + /// + /// May be empty, check result of HasBarcodeData. + /// + PbiRawBarcodeData& BarcodeData(); + + /// \returns reference to BasicData lookup structure + PbiRawBasicData& BasicData(); + + /// \returns reference to MappedData lookup structure + /// + /// May be empty, check result of HasMappedData. + /// + PbiRawMappedData& MappedData(); + + /// \returns reference to reference data lookup structure + /// + /// May be empty, check result of HasReferenceData. + /// + PbiRawReferenceData& ReferenceData(); + + /// \} + +private: + std::string filename_; + PbiFile::VersionEnum version_ = PbiFile::CurrentVersion; + PbiFile::Sections sections_ = PbiFile::ALL; + uint32_t numReads_ = 0; + PbiRawBarcodeData barcodeData_; + PbiRawMappedData mappedData_; + PbiRawReferenceData referenceData_; + PbiRawBasicData basicData_; +}; + +// PBI index caching + +using PbiIndexCache = std::shared_ptr>>; + +PbiIndexCache MakePbiIndexCache(const DataSet& dataset); +PbiIndexCache MakePbiIndexCache(const std::vector&); +PbiIndexCache MakePbiIndexCache(const BamFile& bamFile); + +} // namespace BAM +} // namespace PacBio + +#endif // PBIRAWDATA_H diff --git a/include/pbbam/Position.h b/include/pbbam/Position.h new file mode 100644 index 0000000..6fce22e --- /dev/null +++ b/include/pbbam/Position.h @@ -0,0 +1,35 @@ +// File Description +/// \file Position.h +/// \brief Defines the Position typedef. +// +// Author: Derek Barnett + +#ifndef POSITION_H +#define POSITION_H + +#include "pbbam/Config.h" + +#include + +#include + +namespace PacBio { +namespace BAM { + +/// \brief This type is used to refer to genomic positions. +/// \typedef typedef int32_t PacBio::BAM::Position +/// +/// We use a signed integer because SAM/BAM uses the -1 value to indicate +/// unknown or unmapped positions. +/// +using Position PBBAM_DEPRECATED = PacBio::Data::Position; + +/// \brief This constant is widely used as a "missing" or "invalid" position +/// marker. +/// +PBBAM_DEPRECATED constexpr Position UnmappedPosition{-1}; + +} // namespace BAM +} // namespace PacBio + +#endif // POSITION_H diff --git a/include/pbbam/ProgramInfo.h b/include/pbbam/ProgramInfo.h new file mode 100644 index 0000000..f7101da --- /dev/null +++ b/include/pbbam/ProgramInfo.h @@ -0,0 +1,178 @@ +// File Description +/// \file ProgramInfo.h +/// \brief Defines the ProgramInfo class. +// +// Author: Derek Barnett + +#ifndef PROGRAMINFO_H +#define PROGRAMINFO_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +/// \brief The ProgramInfo class represents a program entry (\@PG) in the SAM +/// header. +/// +class PBBAM_EXPORT ProgramInfo +{ +public: + /// \name Conversion & Validation + /// + + /// \brief Creates a ProgramInfo object from SAM-formatted text. + /// + /// \param[in] sam SAM-formatted text + /// \returns program info object + /// + static ProgramInfo FromSam(const std::string& sam); + + /// \brief Converts a ProgramInfo object to its SAM-formatted text. + /// + /// \param[in] prog input ProgramInfo object + /// \returns SAM-formatted text (no trailing newline) + /// + static std::string ToSam(const ProgramInfo& prog); + + /// \} + +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates a program info object with an ID. + /// + /// \param[in] id program ID (\@PG:ID) + /// + ProgramInfo(std::string id); + + ProgramInfo() = default; + + /// \} + +public: + /// \name Conversion & Validation + /// + + /// \returns true if program info is valid + /// + /// Currently this checks to see that ProgramInfo::Id does not contain an + /// empty string. + /// + bool IsValid() const; + + /// \brief Converts this object to its SAM-formatted text. + /// + /// \returns SAM-formatted text (no trailing newline) + /// + std::string ToSam() const; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// \returns string value of \@PG:CL + std::string CommandLine() const; + + /// \returns any non-standard tags added to the \@PG entry + /// + /// Result map consists of {tagName => value}. + /// + std::map CustomTags() const; + + /// \returns string value of \@PG:DS + std::string Description() const; + + /// \returns string value of \@PG:ID + std::string Id() const; + + /// \returns string value of \@PG:PN + std::string Name() const; + + /// \returns string value of \@PG:PP + std::string PreviousProgramId() const; + + /// \returns string value of \@PG:VN + std::string Version() const; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// \brief Sets the value for \@PG:CL + /// + /// \param[in] cmd new value + /// \returns reference to this object + /// + ProgramInfo& CommandLine(std::string cmd); + + /// \brief Sets a new collection of non-standard tags. + /// + /// Custom tag map entries should consist of {tagName => value}. + /// + /// \param[in] custom new tags + /// \returns reference to this object + /// + ProgramInfo& CustomTags(std::map custom); + + /// \brief Sets the value for \@PG:DS + /// + /// \param[in] description new value + /// \returns reference to this object + /// + ProgramInfo& Description(std::string description); + + /// \brief Sets the value for \@PG:ID + /// + /// \param[in] id new value + /// \returns reference to this object + /// + ProgramInfo& Id(std::string id); + + /// \brief Sets the value for \@PG:PN + /// + /// \param[in] name new value + /// \returns reference to this object + /// + ProgramInfo& Name(std::string name); + + /// \brief Sets the value for \@PG:PP + /// + /// \param[in] id new value + /// \returns reference to this object + /// + ProgramInfo& PreviousProgramId(std::string id); + + /// \brief Sets the value for \@PG:VN + /// + /// \param[in] version new value + /// \returns reference to this object + /// + ProgramInfo& Version(std::string version); + + /// \} + +private: + std::string commandLine_; // CL: + std::string description_; // DS: + std::string id_; // ID: * must be unique for valid SAM * + std::string name_; // PN: + std::string previousProgramId_; // PP: + std::string version_; // VN: + + // custom attributes + std::map custom_; // tag => value +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PROGRAMINFO_H diff --git a/include/pbbam/PulseBehavior.h b/include/pbbam/PulseBehavior.h new file mode 100644 index 0000000..b01fe50 --- /dev/null +++ b/include/pbbam/PulseBehavior.h @@ -0,0 +1,27 @@ +// File Description +/// \file PulseBehavior.h +/// \brief Defines the PulseBehavior enum. +// +// Author: Derek Barnett + +#ifndef PULSEBEHAVIOR_H +#define PULSEBEHAVIOR_H + +#include "pbbam/Config.h" + +namespace PacBio { +namespace BAM { + +/// \brief This enum defines the pulsecall modes supported by BamRecord tag +/// accessors. +/// +enum class PulseBehavior +{ + BASECALLS_ONLY, ///< "Squashed" pulses not included, only basecalls. + ALL ///< All pulses included. +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PULSEBEHAVIOR_H diff --git a/include/pbbam/PulseExclusionReason.h b/include/pbbam/PulseExclusionReason.h new file mode 100644 index 0000000..c5a6ad3 --- /dev/null +++ b/include/pbbam/PulseExclusionReason.h @@ -0,0 +1,30 @@ +// File Description +/// \file PulseExclusionReason.h +/// \brief Defines the PulseExclusionReason enum. +// +// Author: Derek Barnett + +#ifndef PULSE_EXCLUSION_REASON_H +#define PULSE_EXCLUSION_REASON_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +/// \brief This enum defines the possible pulse exclusion reasons +/// +enum class PulseExclusionReason : uint8_t +{ + BASE = 0, + SHORT_PULSE, + BURST, + PAUSE +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PULSE_EXCLUSION_REASON_H diff --git a/include/pbbam/QNameQuery.h b/include/pbbam/QNameQuery.h new file mode 100644 index 0000000..50ebda8 --- /dev/null +++ b/include/pbbam/QNameQuery.h @@ -0,0 +1,60 @@ +// File Description +/// \file QNameQuery.h +/// \brief Defines the QNameQuery class. +// +// Author: Derek Barnett + +#ifndef QNAMEQUERY_H +#define QNAMEQUERY_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The QNameQuery class provides iterable access to a DataSet's records, +/// with each iteration of the query returning a contiguous block of +/// records that share a name. +/// +/// There is no random-access here. It is simply a sequential read-through, +/// grouping contiguous results that share a BamRecord::FullName. +/// +/// \note The name is not ideal - but for legacy reasons, it will remain as-is +/// for now. It will likely become something more explicit, like +/// "SequentialQNameGroupQuery", so that the name "QNameQuery" will be +/// available for a built-in query on a QNAME filter (or whitelist). This +/// will make it more consistent with other queries (ReadAccuracyQuery, +/// SubreadLengthQuery, ZmwQuery, etc). +/// +class PBBAM_EXPORT QNameQuery : public internal::IGroupQuery +{ +public: + /// \brief Creates a new QNameQuery. + /// + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM files + /// + QNameQuery(const DataSet& dataset); + ~QNameQuery() override; + + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(std::vector& records) override; + +private: + class QNameQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // QNAMEQUERY_H diff --git a/include/pbbam/QualityValue.h b/include/pbbam/QualityValue.h new file mode 100644 index 0000000..14b9e5b --- /dev/null +++ b/include/pbbam/QualityValue.h @@ -0,0 +1,26 @@ +// File Description +/// \file QualityValue.h +/// \brief Defines the QualityValue class. +// +// Author: Derek Barnett + +#ifndef QUALITYVALUE_H +#define QUALITYVALUE_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +using QualityValue PBBAM_DEPRECATED = PacBio::Data::QualityValue; + +} // namespace BAM +} // namespace PacBio + +#endif // QUALITYVALUE_H diff --git a/include/pbbam/QualityValues.h b/include/pbbam/QualityValues.h new file mode 100644 index 0000000..5158244 --- /dev/null +++ b/include/pbbam/QualityValues.h @@ -0,0 +1,28 @@ +// File Description +/// \file QualityValues.h +/// \brief Defines the QualityValues class. +// +// Author: Derek Barnett + +#ifndef QUALITYVALUES_H +#define QUALITYVALUES_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +#include "pbbam/QualityValue.h" + +namespace PacBio { +namespace BAM { + +using QualityValues PBBAM_DEPRECATED = PacBio::Data::QualityValues; + +} // namespace BAM +} // namespace PacBio + +#endif // QUALITYVALUES_H diff --git a/include/pbbam/ReadAccuracyQuery.h b/include/pbbam/ReadAccuracyQuery.h new file mode 100644 index 0000000..6fcea10 --- /dev/null +++ b/include/pbbam/ReadAccuracyQuery.h @@ -0,0 +1,69 @@ +// File Description +/// \file ReadAccuracyQuery.h +/// \brief Defines the ReadAccuracyQuery class. +// +// Author: Derek Barnett + +#ifndef READACCURACYQUERY_H +#define READACCURACYQUERY_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/Accuracy.h" +#include "pbbam/Compare.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The ReadAccuracyQuery class provides iterable access to a DataSet's +/// %BAM records, limiting results to those matching a read accuracy +/// criterion. +/// +/// Example: +/// \include code/ReadAccuracyQuery.txt +/// +/// \note Currently, all %BAM files must have a corresponding ".pbi" index file. +/// Use BamFile::EnsurePacBioIndexExists before creating the query if one +/// may not be present. +/// +class PBBAM_EXPORT ReadAccuracyQuery : public internal::IQuery +{ +public: + /// \brief Creates a new ReadAccuracyQuery, limiting record results to only + /// those matching a read accuracy criterion. + /// + /// \param[in] accuracy read accuracy value + /// \param[in] compareType compare operator + /// \param[in] dataset input data source(s) + /// + /// \sa BamRecord::ReadAccuracy + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or PBI + /// files. + /// + ReadAccuracyQuery(const Accuracy accuracy, const Compare::Type compareType, + const DataSet& dataset); + + ~ReadAccuracyQuery() override; + + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(BamRecord& r) override; + + uint32_t NumReads() const; + +private: + class ReadAccuracyQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // READACCURACYQUERY_H diff --git a/include/pbbam/ReadGroupInfo.h b/include/pbbam/ReadGroupInfo.h new file mode 100644 index 0000000..3d86142 --- /dev/null +++ b/include/pbbam/ReadGroupInfo.h @@ -0,0 +1,713 @@ +// File Description +/// \file ReadGroupInfo.h +/// \brief Defines the ReadGroupInfo class. +// +// Author: Derek Barnett + +#ifndef READGROUPINFO_H +#define READGROUPINFO_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include + +#include "pbbam/exception/InvalidSequencingChemistryException.h" + +namespace PacBio { +namespace BAM { + +/// \brief This enum describes the base features that may be present in a read +/// group's records. +/// +/// This information is stored in its description (\@RG:DS). +/// +enum class BaseFeature +{ + DELETION_QV, + DELETION_TAG, + INSERTION_QV, + MERGE_QV, + SUBSTITUTION_QV, + SUBSTITUTION_TAG, + IPD, + PULSE_WIDTH, + PKMID, + PKMEAN, + PKMID2, + PKMEAN2, + LABEL, + LABEL_QV, + ALT_LABEL, + ALT_LABEL_QV, + PULSE_MERGE_QV, + PULSE_CALL, + PRE_PULSE_FRAMES, + PULSE_CALL_WIDTH, + START_FRAME, + PULSE_EXCLUSION +}; + +/// \brief This enum describes the encoding types used for frame data within a +/// read group's records. +/// +/// This information is stored in its description (\@RG:DS). +/// +enum class FrameCodec +{ + RAW, + V1 +}; + +/// \brief This enum describes the experimental design of the barcodes within a +/// read group's records. +/// +/// This information is stored in its description (\@RG:DS). +/// +enum class BarcodeModeType +{ + NONE, + SYMMETRIC, + ASYMMETRIC, + TAILED +}; + +/// \brief This enum describes the type of value encoded by barcode quality, +/// within a read group's records. +/// +/// This information is stored in its description (\@RG:DS). +/// +enum class BarcodeQualityType +{ + NONE, + SCORE, + PROBABILITY +}; + +/// \brief This enum describes the instrument type / platform model, +/// within a read group's records. +/// +/// This information is stored in its description (\@RG:PM). +/// +enum class PlatformModelType +{ + ASTRO, + RS, + SEQUEL, + SEQUELII +}; + +/// \brief The ReadGroupInfo class represents a read group entry (\@RG) in the +/// SAM header. +/// +class PBBAM_EXPORT ReadGroupInfo +{ +public: + /// \name Conversion & Validation + /// + + /// \brief Creates a ReadGroupInfo object from SAM-formatted text. + /// + /// \param[in] sam SAM-formatted text + /// \returns read group info object + /// + static ReadGroupInfo FromSam(const std::string& sam); + + /// \brief Converts a ReadGroupInfo object to its SAM-formatted text. + /// + /// \param[in] rg input ReadGroupInfo object + /// \returns SAM-formatted text (no trailing newline) + /// + static std::string ToSam(const ReadGroupInfo& rg); + + /// + /// \brief GetBaseId + /// + /// \param id + /// \return the hash portion only of a read group ID, with (optional) + /// barcode labels removed) + /// + /// \sa ReadGroupInfo::BaseId + /// + static std::string GetBaseId(const std::string& id); + + /// \brief Converts a read group ID (string) to its numeric value. + /// + /// \note Accepts the optional barcode-labeled IDs. These will be stripped + /// and number calculated from the base value. + /// + /// \param[in] rgId read group ID string + /// \returns numeric value of ID + /// + static int32_t IdToInt(const std::string& rgId); + + /// \brief Converts a read group ID number to its string representation. + /// + /// \param[in] id read group ID number + /// \returns hexadecimal string representation of ID + /// + static std::string IntToId(const int32_t id); + + /// \returns sequencing chemistry from (bindingKig, sequencingKit, + /// basecallerVersion) + /// + static std::string SequencingChemistryFromTriple(const std::string& bindingKit, + const std::string& sequencingKit, + const std::string& basecallerVersion); + + /// \} + +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates an empty read group of UNKNOWN read type. + ReadGroupInfo(); + + /// \brief Creates a read group info object with an ID. + /// + /// \note \p id can be a "standard" ID or contain barcode labels. + /// + /// \param[in] id string representation of read group ID + /// + ReadGroupInfo(std::string id); + + /// \brief Creates a read group info object from a movie name & read type. + /// + /// \param[in] movieName sequencing movie name + /// \param[in] readType string version of record type + /// + /// \sa RecordType + /// + ReadGroupInfo(std::string movieName, std::string readType); + + /// \brief Creates a read group info object from a movie name, read type, + /// and platform model. + /// + /// \param[in] movieName sequencing movie name + /// \param[in] readType string version of record type + /// \param[in] platform platform model type + /// + /// \sa RecordType + /// + ReadGroupInfo(std::string movieName, std::string readType, PlatformModelType platform); + + /// \brief Creates a read group info object with an ID. + /// + /// \param[in] baseId string representation of numeric read group ID + /// \param[in] barcodes barcode pair for this read group + /// + ReadGroupInfo(std::string baseId, std::pair barcodes); + + /// \brief Creates a read group info object from a movie name & read type. + /// + /// \param[in] movieName sequencing movie name + /// \param[in] readType string version of record type + /// \param[in] barcodes barcode pair for this read group + /// + /// \sa RecordType + /// + ReadGroupInfo(std::string movieName, std::string readType, + std::pair barcodes); + + /// \brief Creates a read group info object from a movie name, read type, + /// and platform model. + /// + /// \param[in] movieName sequencing movie name + /// \param[in] readType string version of record type + /// \param[in] platform platform model type + /// \param[in] barcodes barcode pair for this read group + /// + /// \sa RecordType + /// + ReadGroupInfo(std::string movieName, std::string readType, PlatformModelType platform, + std::pair barcodes); + + /// \} + +public: + /// \name Comparison Operators + /// \{ + + bool operator==(const ReadGroupInfo& other) const; + + /// Enable sort on RG:ID + bool operator<(const ReadGroupInfo& other) const; + + /// \} + +public: + /// \name Conversion & Validation + /// \{ + + /// \returns true if read group info is valid + /// + /// Currently this checks to see that ReadGroupInfo::Id does not contain an + /// empty string. + /// + bool IsValid() const; + + /// \brief Converts this object to its SAM-formatted text. + /// + /// \returns SAM-formatted text (no trailing newline) + /// + std::string ToSam() const; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// \returns the number of barcode sequences in BarcodeFile, as stored in + /// the description tag (\@RG:DS) + /// + /// \throws std::runtime_error if barcode data not set. + /// Check HasBarcodeData if this data may be absent. + /// + size_t BarcodeCount() const; + + /// \returns name of FASTA file containing barcode sequences, as stored in + /// the description tag (\@RG:DS) + /// + /// \throws std::runtime_error if barcode data not set. + /// Check HasBarcodeData if this data may be absent. + /// + std::string BarcodeFile() const; + + /// \returns MD5 hash of the contents of BarcodeFile, as stored in the + /// description tag (\@RG:DS) + /// + /// \throws std::runtime_error if barcode data not set. + /// Check HasBarcodeData if this data may be absent. + /// + std::string BarcodeHash() const; + + /// \returns experimental design type of barcodes, as stored in the + /// description tag (\@RG:DS) + /// + /// \throws std::runtime_error if barcode data not set. + /// Check HasBarcodeData if this data may be absent. + /// + BarcodeModeType BarcodeMode() const; + + /// \returns type of value encoded by the 'bq' tag, as stored in the + /// description tag (\@RG:DS) + /// + /// \throws std::runtime_error if barcode data is not set. + /// Check HasBarcodeData if this data may be absent. + /// + BarcodeQualityType BarcodeQuality() const; + + /// \returns barcode pair stored in the read group ID (\@RG:ID) + /// + /// \note This does **NOT** refer to any data in the description (DS) tag. + /// + boost::optional> Barcodes() const; + + /// \returns forward barcode label stored in the read group ID (\@RG:ID) + /// + /// \note This does **NOT** refer to any data in the description (DS) tag. + /// + boost::optional BarcodeForward() const; + + /// \returns reverse barcode label stored in the read group ID (\@RG:ID) + /// + /// \note This does **NOT** refer to any data in the description (DS) tag. + /// + boost::optional BarcodeReverse() const; + + /// \returns basecaller version number (e.g. "2.1") + std::string BasecallerVersion() const; + + /// \returns tag name in use for the specified for base feature + std::string BaseFeatureTag(BaseFeature feature) const; + + /// \returns the hash portion only of a read group ID, with (optional) + /// barcode labels removed) + /// + /// For most read groups (without barcode labels), this will be the same as + /// ID(). However, for those read groups with barcoded-labels, this method + /// will return the ID without those labels. + /// + /// Id() should be preferred over this method in most cases. This is + /// intended for use with hash-string or integers directly. + /// + /// For "ID:12345678": + /// rg.Id() -> "12345678" + /// rg.BaseId() -> "12345678" + /// + /// For "ID:12345678/0--0": + /// rg.Id() -> "12345678/0--0"; + /// rg.BaseId -> "12345678" + /// + /// \sa Id + /// + std::string BaseId() const; + + /// \returns binding kit part number (e.g. "100236500") + std::string BindingKit() const; + + /// \returns true if reads are classified as spike-in controls + bool Control() const; + + /// \returns any non-standard tags added to the \@PG entry + /// + /// Result map consists of {tagName => value}. + /// + std::map CustomTags() const; + + /// \returns string value of \@RG:DT + std::string Date() const; + + /// \returns string value of \@RG:FO + std::string FlowOrder() const; + + /// \returns frame rate in Hz + std::string FrameRateHz() const; + + /// \returns true if the read group description (\@RG:DS) contains barcode data + /// + /// \note This does **NOT** refer to the optional barcode labels. + /// + bool HasBarcodeData() const; + + /// \returns true if read group has an entry for the specified base feature + bool HasBaseFeature(BaseFeature feature) const; + + /// \returns full string value of \@RG:ID, whether optional barcode labels + /// are present + /// + /// This method should be perferred over BaseId() in most cases, + /// e.g. mapping between header info. + /// + /// For "ID:12345678": + /// rg.Id() -> "12345678" + /// rg.BaseId() -> "12345678" + /// + /// For "ID:12345678/0--0": + /// rg.Id() -> "12345678/0--0"; + /// rg.BaseId -> "12345678" + /// + /// \sa BaseId + /// + std::string Id() const; + + /// \returns codec type in use for IPD + FrameCodec IpdCodec() const; + + /// \returns string value of \@RG:KS + std::string KeySequence() const; + + /// \returns string value of \@RG:LB + std::string Library() const; + + /// \returns movie name (stored in \@RG:PU) + std::string MovieName() const; + + /// \returns string value of \@RG:PL + std::string Platform() const; + + /// \returns string value of \@RG:PM + PlatformModelType PlatformModel() const; + + /// \returns string value of \@RG:PI + std::string PredictedInsertSize() const; + + /// \returns string value of \@RG:PG + std::string Programs() const; + + /// \returns codec type in use for PulseWidth + FrameCodec PulseWidthCodec() const; + + /// \returns string value of read type + std::string ReadType() const; + + /// \returns string value of \@RG:SM + std::string Sample() const; + + /// \returns string value of \@RG:CN + std::string SequencingCenter() const; + + /// \returns sequencing chemistry name + std::string SequencingChemistry() const; + + /// \returns sequencing kit part number + std::string SequencingKit() const; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// \brief Sets barcode data for the read group's description tag. + /// + /// Barcode fields are either absent or all must be present. + /// + /// \param[in] barcodeFile barcode filename + /// \param[in] barcodeHash MD5 hash of barcode file + /// \param[in] barcodeCount number of records in barcode file + /// \param[in] barcodeMode experimental design of barcodes + /// \param[in] barcodeQuality type of barcode quality value + /// + /// \sa BarcodeFile \n + /// BarcodeHash \n + /// BarcodeCount \n + /// BarcodeMode \n + /// BarcodeQuality \n + /// ReadGroupInfo::ClearBarcodeData + /// + /// \returns reference to this object + /// + ReadGroupInfo& BarcodeData(std::string barcodeFile, std::string barcodeHash, + size_t barcodeCount, BarcodeModeType barcodeMode, + BarcodeQualityType barcodeQuality); + + /// \brief Sets the basecaller version number. + /// + /// \param[in] versionNumber new value + /// \returns reference to this object + /// + ReadGroupInfo& BasecallerVersion(std::string versionNumber); + + /// \brief Sets the tag to be used for a particular base feature. + /// + /// \param[in] feature feature type begin updated + /// \param[in] tag new value + /// \returns reference to this object + /// + ReadGroupInfo& BaseFeatureTag(BaseFeature feature, std::string tag); + + /// \brief Sets the binding kit part number. + /// + /// \param[in] kitNumber new value + /// \returns reference to this object + /// + ReadGroupInfo& BindingKit(std::string kitNumber); + + /// \brief Removes all barcode data from this read group. + /// + /// \returns reference to this read group + /// + ReadGroupInfo& ClearBarcodeData(); + + /// \brief Removes all base features from this read group. + /// + /// \returns reference to this read group + /// + ReadGroupInfo& ClearBaseFeatures(); + + /// \brief Sets whether read group's records are classifed as spike-in + /// controls. + /// + /// \param[in] ctrl true if records are spike-in controls + /// \returns reference to this object + /// + ReadGroupInfo& Control(bool ctrl); + + /// \brief Sets a new collection of non-standard tags. + /// + /// Custom tag map entries should consist of {tagName => value}. + /// + /// \param[in] custom new tags + /// \returns reference to this object + /// + ReadGroupInfo& CustomTags(std::map custom); + + /// \brief Sets the value for \@RG:DT + /// + /// \param[in] date new value + /// \returns reference to this object + /// + ReadGroupInfo& Date(std::string date); + + /// \brief Sets the value for \@RG:FO + /// + /// \param[in] order new value + /// \returns reference to this object + /// + ReadGroupInfo& FlowOrder(std::string order); + + /// \brief Sets the frame rate. + /// + /// \param[in] frameRateHz string value of frame rate in Hz + /// \returns reference to this object + /// + ReadGroupInfo& FrameRateHz(std::string frameRateHz); + + /// \brief Sets the read group's ID. + /// + /// \param[in] id string value of ID + /// \returns reference to this object + /// + ReadGroupInfo& Id(std::string id); + + /// \brief Sets the read group's ID, from movie name & read type + /// + /// \param[in] movieName sequencing movie name + /// \param[in] readType string version of read type + /// \returns reference to this object + /// + ReadGroupInfo& Id(const std::string& movieName, const std::string& readType); + + /// \brief Sets the codec type used for IPD + /// + /// \param[in] codec codec type + /// \param[in] tag IPD tag + /// \returns reference to this object + /// + ReadGroupInfo& IpdCodec(FrameCodec codec, std::string tag = std::string()); + + /// \brief Sets the value for \@RG:KS + /// + /// \param[in] sequence new value + /// \returns reference to this object + /// + ReadGroupInfo& KeySequence(std::string sequence); + + /// \brief Sets the value for \@RG:LB + /// + /// \param[in] library new value + /// \returns reference to this object + /// + ReadGroupInfo& Library(std::string library); + + /// \brief Sets the value for movie name (stored in \@RG:PU). + /// + /// \param[in] movieName new value + /// \returns reference to this object + /// + ReadGroupInfo& MovieName(std::string movieName); + + /// \brief Sets the value for \@RG:PI + /// + /// \param[in] size new value + /// \returns reference to this object + /// + ReadGroupInfo& PredictedInsertSize(std::string size); + + /// \brief Sets the value for \@RG:PG + /// + /// \param[in] programs new value + /// \returns reference to this object + /// + ReadGroupInfo& Programs(std::string programs); + + /// \brief Sets the value for \@RG:PM + /// + /// \param[in] platformModel new value + /// \returns reference to this object + /// + ReadGroupInfo& PlatformModel(PlatformModelType platform); + + /// \brief Sets the codec type used for PulseWidth + /// + /// \param[in] codec codec type + /// \param[in] tag pulse width tag + /// \returns reference to this object + /// + ReadGroupInfo& PulseWidthCodec(FrameCodec codec, std::string tag = std::string()); + + /// \brief Sets the read type. + /// + /// \param[in] type new value + /// \returns reference to this object + /// + ReadGroupInfo& ReadType(std::string type); + + /// \brief Removes a particular base feature from this read group. + /// + /// \param[in] feature feature to remove + /// \returns reference to this object + /// + ReadGroupInfo& RemoveBaseFeature(BaseFeature feature); + + /// \brief Sets the value for \@RG:SM + /// + /// \param[in] sample new value + /// \returns reference to this object + /// + ReadGroupInfo& Sample(std::string sample); + + /// \brief Sets the value for \@RG:CN + /// + /// \param[in] center new value + /// \returns reference to this object + /// + ReadGroupInfo& SequencingCenter(std::string center); + + /// \brief Sets the sequencing kit part number. + /// + /// \param[in] kitNumber new value + /// \returns reference to this object + /// + ReadGroupInfo& SequencingKit(std::string kitNumber); + + /// \} + +private: + std::string id_; // ID * must be unique for valid SAM * + std::string sequencingCenter_; // CN + std::string date_; // DT * (ISO-8601) * + std::string flowOrder_; // FO + std::string keySequence_; // KS + std::string library_; // LB + std::string programs_; // PG + std::string predictedInsertSize_; // PI + std::string movieName_; // PU + std::string sample_; // SM + + PlatformModelType platformModel_ = PlatformModelType::SEQUEL; // PM + + // DS: components + std::string readType_; + std::string bindingKit_; + std::string sequencingKit_; + std::string basecallerVersion_; + mutable std::string sequencingChemistry_; + std::string frameRateHz_; + bool control_ = false; + FrameCodec ipdCodec_ = FrameCodec::V1; + FrameCodec pulseWidthCodec_ = FrameCodec::V1; + bool hasBarcodeData_ = false; + std::string barcodeFile_; + std::string barcodeHash_; + size_t barcodeCount_ = 0; + BarcodeModeType barcodeMode_ = BarcodeModeType::NONE; + BarcodeQualityType barcodeQuality_ = BarcodeQualityType::NONE; + std::map features_; + + // (optional) barcode label handling + boost::optional> barcodes_ = boost::none; + std::string baseId_; + + // custom attributes + std::map custom_; // tag => value + +private: + std::string EncodeSamDescription() const; + void DecodeSamDescription(const std::string& description); + void DecodeBarcodeKey(const std::string& key, std::string value); + void DecodeFrameCodecKey(const std::string& key, std::string value); +}; + +/// \brief Creates a read group ID from a movie name & read type. +/// +/// \param[in] movieName sequencing movie name +/// \param[in] readType string version of read type +/// +/// \returns hexadecimal string read group ID +/// +PBBAM_EXPORT +std::string MakeReadGroupId(const std::string& movieName, const std::string& readType); + +} // namespace BAM +} // namespace PacBio + +#endif // READGROUPINFO_H diff --git a/include/pbbam/RecordType.h b/include/pbbam/RecordType.h new file mode 100644 index 0000000..856d831 --- /dev/null +++ b/include/pbbam/RecordType.h @@ -0,0 +1,56 @@ +// File Description +/// \file RecordType.h +/// \brief Defines the RecordType enum. +// +// Author: Derek Barnett + +#ifndef RECORDTYPE_H +#define RECORDTYPE_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +/// \brief This enum defines the possible PacBio BAM record types. +/// +/// \sa ReadGroupInfo::ReadType +/// +enum class RecordType +{ + ZMW, ///< Polymerase read + HQREGION, ///< High-quality region + SUBREAD, ///< Subread + CCS, ///< Circular consensus sequence + SCRAP, ///< Additional sequence (barcodes, adapters, etc.) + UNKNOWN, ///< Unknown read type + TRANSCRIPT, ///< Transcript + + POLYMERASE = ZMW ///< \deprecated as of PacBio BAM spec v 3.0.4 (use RecordType::ZMW instead) +}; + +/// +/// \brief IsCcsOrTranscript +/// +/// CCS & Transcript type records handle queryStart/End in the same way. This +/// status is checked in several places, so this is a convenient helper. +/// +/// \param[in] type +/// +bool IsCcsOrTranscript(const RecordType type); + +/// +/// \brief Returns string representation of RecordType +/// +/// \param type +/// \return std::string +/// \throws std::runtime_error if type is unrecognized +/// +std::string ToString(const RecordType type); + +} // namespace BAM +} // namespace PacBio + +#endif // RECORDTYPE_H diff --git a/include/pbbam/SNR.h b/include/pbbam/SNR.h new file mode 100644 index 0000000..95a9f1c --- /dev/null +++ b/include/pbbam/SNR.h @@ -0,0 +1,27 @@ +// File Description +/// \file SNR.h +/// \brief Defines the SNR struct +// +// Author: Lance Hepler, Derek Barnett + +#ifndef SNR_H +#define SNR_H + +#include "pbbam/Config.h" + +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +using SNR PBBAM_DEPRECATED = PacBio::Data::SNR; + +PBBAM_DEPRECATED constexpr auto ClampSNR = PacBio::Data::ClampSNR; + +} // namespace BAM +} // namespace PacBio + +#endif // SNR_H diff --git a/include/pbbam/SamTagCodec.h b/include/pbbam/SamTagCodec.h new file mode 100644 index 0000000..0c9ad89 --- /dev/null +++ b/include/pbbam/SamTagCodec.h @@ -0,0 +1,68 @@ +// File Description +/// \file SamTagCodec.h +/// \brief Defines the SamTagCodec class. +// +// Author: Derek Barnett + +#ifndef SAMTAGCODEC_H +#define SAMTAGCODEC_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/TagCollection.h" + +namespace PacBio { +namespace BAM { + +/// \brief The SamTagCodec class provides text-based encoding/decoding of %BAM +/// tag data. +/// +/// \note SamTagCodec is mostly an implementation and/or testing detail, and may +/// be removed from the public API. +/// +class PBBAM_EXPORT SamTagCodec +{ +public: + /// \name Tag Collection Methods + /// \{ + + /// \brief Creates a TagCollection from SAM-formatted tag data. + /// + /// \param[in] tagString SAM-formmated string + /// \returns resulting tag collection + /// + static TagCollection Decode(const std::string& tagString); + + /// \brief Creates SAM-formatted string from a Tag. + /// + /// \param[in] name 2-character tag name + /// \param[in] tag Tag instance containing data + /// + /// \return SAM-formatted string + /// + static std::string Encode(const std::string& name, const PacBio::BAM::Tag& tag); + + /// \brief Creates SAM-formatted string from a TagCollection. + /// + /// \param[in] tags TagCollection containing tag data + /// \returns SAM-formatted string + /// + static std::string Encode(const PacBio::BAM::TagCollection& tags); +}; + +/// +/// \brief creates a tag per the SAM/BAM text format +/// +/// \param tag tag name +/// \param value tag value +/// +/// \return formatted tag string +/// +std::string MakeSamTag(std::string tag, std::string value); + +} // namespace BAM +} // namespace PacBio + +#endif // SAMTAGCODEC_H diff --git a/include/pbbam/SamWriter.h b/include/pbbam/SamWriter.h new file mode 100644 index 0000000..f0409bc --- /dev/null +++ b/include/pbbam/SamWriter.h @@ -0,0 +1,96 @@ +// File Description +/// \file SamWriter.h +/// \brief Defines the SamWriter class. +// +// Author: Derek Barnett + +#ifndef SAMWRITER_H +#define SAMWRITER_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/IRecordWriter.h" + +namespace PacBio { +namespace BAM { + +/// \brief The SamWriter class provides a writing interface for creating +/// new SAM files. +/// +/// \note The underlying buffered data may not be flushed to the file until the +/// destructor is called. Trying to access the file (reading, stat-ing, +/// indexing, etc.) before the SamWriter is destroyed yields undefined +/// behavior. Enclose the SamWriter in some form of local scope (curly +/// braces, a separate function, etc.) to ensure that its destructor is +/// called before proceeding to read-based operations. +/// +/// \code{.cpp} +/// { +/// SamWriter w(...); +/// // write data +/// } +/// // now safe to access the new file +/// \endcode +/// +/// +class SamWriter : public IRecordWriter +{ +public: + /// \brief Opens a SAM file for writing & writes the header information. + /// + /// \note Set \p filename to "-" for stdout. + /// + /// \param[in] filename path to output SAM file + /// \param[in] header BamHeader object + /// + /// \throws std::runtime_error if there was a problem opening the file for + /// writing or if an error occurred while writing the header + /// + SamWriter(std::string filename, const BamHeader& header); + + /// Fully flushes all buffered data & closes file. + /// + SamWriter(SamWriter&&) noexcept; + SamWriter& operator=(SamWriter&&) noexcept; + ~SamWriter() override; + + /// \brief Try to flush any buffered data to file. + /// + /// \note The underlying implementation may not necessarily flush buffered + /// data immediately, especially in a multithreaded writer situation. + /// Let the SamWriter go out of scope to fully ensure flushing. + /// + /// \throws std::runtime_error if flush fails + /// + void TryFlush() override; + + /// \brief Write a record to the output SAM file. + /// + /// \param[in] record BamRecord object + /// + /// \throws std::runtime_error on failure to write + /// + void Write(const BamRecord& record) override; + + /// \brief Write a record to the output SAM file. + /// + /// \param[in] recordImpl BamRecordImpl object + /// + /// \throws std::runtime_error on failure to write + /// + void Write(const BamRecordImpl& recordImpl) override; + +private: + class SamWriterPrivate; + std::unique_ptr d_; +}; + +} // namesapce BAM +} // namespace PacBio + +#endif // SAMWRITER_H diff --git a/include/pbbam/SequenceInfo.h b/include/pbbam/SequenceInfo.h new file mode 100644 index 0000000..5361b01 --- /dev/null +++ b/include/pbbam/SequenceInfo.h @@ -0,0 +1,188 @@ +// File Description +/// \file SequenceInfo.h +/// \brief Defines the SequenceInfo class. +// +// Author: Derek Barnett + +#ifndef SEQUENCEINFO_H +#define SEQUENCEINFO_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +/// \brief The SequenceInfo class represents a program entry (\@SQ) in the SAM +/// header. +/// +class PBBAM_EXPORT SequenceInfo +{ +public: + /// \name Conversion & Validation + /// + + /// \brief Creates a SequenceInfo object from SAM-formatted text. + /// + /// \param[in] sam SAM-formatted text + /// \returns program info object + /// + static SequenceInfo FromSam(const std::string& sam); + + /// \brief Converts a SequenceInfo object to its SAM-formatted text. + /// + /// \param[in] seq input SequenceInfo object + /// \returns SAM-formatted text (no trailing newline) + /// + static std::string ToSam(const SequenceInfo& seq); + + /// \} + +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates a sequence info object with name & (optional) length. + /// + /// \param[in] name sequence name (\@SQ:SN) + /// \param[in] length sequence length (\@SQ:LN) + /// + SequenceInfo(std::string name, std::string length = "0"); + + SequenceInfo() = default; + + /// \} + +public: + /// \name Operators + /// \{ + + bool operator==(const SequenceInfo& other) const; + bool operator!=(const SequenceInfo& other) const; + + /// \} + +public: + /// \name Conversion & Validation + /// + + /// \returns true if sequence info is valid + /// + /// Currently this checks to see that Name is non-empty and Length is within + /// the accepted range. + /// + bool IsValid() const; + + /// \brief Converts this object to its SAM-formatted text. + /// + /// \returns SAM-formatted text (no trailing newline) + /// + std::string ToSam() const; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// \returns string value of \@SQ:AS + std::string AssemblyId() const; + + /// \returns string value of \@SQ:M5 + std::string Checksum() const; + + /// \returns any non-standard tags added to the \@PG entry + /// + /// Result map consists of {tagName => value}. + /// + std::map CustomTags() const; + + /// \returns string value of \@SQ:LN + std::string Length() const; + + /// \returns string value of \@SQ:SN + std::string Name() const; + + /// \returns string value of \@SQ:SP + std::string Species() const; + + /// \returns string value of \@SQ:UR + std::string Uri() const; + + /// \} + +public: + /// \name Attributes + /// \{ + + /// \brief Sets the value for \@SQ:AS + /// + /// \param[in] id new value + /// \returns reference to this object + /// + SequenceInfo& AssemblyId(std::string id); + + /// \brief Sets the value for \@SQ:M5 + /// + /// \param[in] checksum new value + /// \returns reference to this object + /// + SequenceInfo& Checksum(std::string checksum); + + /// \brief Sets a new collection of non-standard tags. + /// + /// Custom tag map entries should consist of {tagName => value}. + /// + /// \param[in] custom new tags + /// \returns reference to this object + /// + SequenceInfo& CustomTags(std::map custom); + + /// \brief Sets the value for \@SQ:LN + /// + /// \param[in] length new value + /// \returns reference to this object + /// + SequenceInfo& Length(std::string length); + + /// \brief Sets the value for \@SQ:SN + /// + /// \param[in] name new value + /// \returns reference to this object + /// + SequenceInfo& Name(std::string name); + + /// \brief Sets the value for \@SQ:SP + /// + /// \param[in] species new value + /// \returns reference to this object + /// + SequenceInfo& Species(std::string species); + + /// \brief Sets the value for \@SQ:UR + /// + /// \param[in] uri new value + /// \returns reference to this object + /// + SequenceInfo& Uri(std::string uri); + + /// \} + +private: + std::string name_; // SN: * must be unique for valid SAM * + std::string length_; // LN: * must be within [0 - 2^31-1] * + std::string assemblyId_; // AS: + std::string checksum_; // M5: + std::string species_; // SP: + std::string uri_; // UR: + + // custom attributes + std::map custom_; // tag => value +}; + +} // namespace BAM +} // namespace PacBio + +#endif // SEQUENCEINFO_H diff --git a/include/pbbam/Strand.h b/include/pbbam/Strand.h new file mode 100644 index 0000000..d27945f --- /dev/null +++ b/include/pbbam/Strand.h @@ -0,0 +1,22 @@ +// File Description +/// \file Strand.h +/// \brief Defines the Strand enum. +// +// Author: Derek Barnett + +#ifndef STRAND_H +#define STRAND_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace BAM { + +using Strand PBBAM_DEPRECATED = PacBio::Data::Strand; + +} // namespace BAM +} // namespace PacBio + +#endif // STRAND_H diff --git a/include/pbbam/StringUtilities.h b/include/pbbam/StringUtilities.h new file mode 100644 index 0000000..abc90e1 --- /dev/null +++ b/include/pbbam/StringUtilities.h @@ -0,0 +1,44 @@ +// Author: Derek Barnett + +#ifndef PBBAM_STRINGUTILITIES_H +#define PBBAM_STRINGUTILITIES_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +/// +/// \brief Joins tokens into a single string +/// +/// \param tokens input strings +/// \param delim delimiter character +/// +/// \return joined string +/// +std::string Join(const std::vector& tokens, const char delim); + +/// \brief Splits a string into tokens +/// +/// \param[in] line input string +/// \param[in] delim character to split on +/// +/// \returns vector of tokens +/// +std::vector Split(const std::string& line, const char delim = '\t'); + +/// \brief Remove all whitespace from input string (start, end, & internal) +/// +/// \param[in] input original string +/// +/// \returns new string with no whitespace +/// +std::string RemoveAllWhitespace(std::string input); + +} // namespace BAM +} // namespace PacBio + +#endif // PBBAM_STRINGUTILITIES_H diff --git a/include/pbbam/SubreadLengthQuery.h b/include/pbbam/SubreadLengthQuery.h new file mode 100644 index 0000000..aa17fb6 --- /dev/null +++ b/include/pbbam/SubreadLengthQuery.h @@ -0,0 +1,67 @@ +// File Description +/// \file SubreadLengthQuery.h +/// \brief Defines the SubreadLengthQuery class. +// +// Author: Derek Barnett + +#ifndef SUBREADLENGTHQUERY_H +#define SUBREADLENGTHQUERY_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/Compare.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The SubreadLengthQuery class provides iterable access to a DataSet's +/// %BAM records, limiting results to those matching a subread length +/// criterion. +/// +/// Example: +/// \include code/SubreadLengthQuery.txt +/// +/// \note Currently, all %BAM files must have a corresponding ".pbi" index file. +/// Use BamFile::EnsurePacBioIndexExists before creating the query if one +/// may not be present. +/// +class PBBAM_EXPORT SubreadLengthQuery : public internal::IQuery +{ +public: + /// \brief Creates a new SubreadLengthQuery, limiting record results to only + /// those matching a subread length criterion. + /// + /// \param[in] length subread length value + /// \param[in] compareType compare operator + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or PBI + /// files. + /// + SubreadLengthQuery(const int32_t length, const Compare::Type compareType, + const DataSet& dataset); + + ~SubreadLengthQuery(); + + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(BamRecord& r) override; + + uint32_t NumReads() const; + +private: + class SubreadLengthQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // SUBREADLENGTHQUERY_H diff --git a/include/pbbam/Tag.h b/include/pbbam/Tag.h new file mode 100644 index 0000000..79cdaf7 --- /dev/null +++ b/include/pbbam/Tag.h @@ -0,0 +1,413 @@ +// File Description +/// \file Tag.h +/// \brief Defines the Tag class. +// +// Author: Derek Barnett + +#ifndef TAG_H +#define TAG_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +/// \brief This enum is used to describe the exact (C++) data type held by a +/// Tag. +/// +enum class TagDataType +{ + INVALID = 0, ///< boost::blank + INT8, ///< int8_t + UINT8, ///< uint8_t + INT16, ///< int16_t + UINT16, ///< uint16_t + INT32 = 5, ///< int32_t + UINT32, ///< uint32_t + FLOAT, ///< float + STRING, ///< std::string + INT8_ARRAY, ///< std::vector + UINT8_ARRAY = 10, ///< std::vector + INT16_ARRAY, ///< std::vector + UINT16_ARRAY, ///< std::vector + INT32_ARRAY, ///< std::vector + UINT32_ARRAY, ///< std::vector + FLOAT_ARRAY = 15 ///< std::vector +}; + +/// \brief This enum provides additional instructions on interpreting the tag's +/// value. +/// +/// Some C++ data types (e.g. std::string) may represent more than one BAM tag +/// type ('H' vs 'Z'). Thus a TagModifier may be used to indicate how to +/// properly distinguish between these shared data types. +/// +enum class TagModifier +{ + /// \brief This value indicates that the tag has no modifiers set. + /// + NONE = 0, + + /// \brief This modifier marks an integer as ASCII. + /// + /// SAM/BAM has the concept of an ASCII character that is distinct from an + /// 8-bit integer. However, there is no such pure separation in C++ - as + /// int8_t/uint8_t are likely implemented as typedefs around char/unsigned + /// char. Thus this modifier can be used to indicate a tag's value should be + /// interpreted as a printable, ASCII character. + /// + ASCII_CHAR, + + /// \brief This modifier marks std::string data as "hex string", rather than + /// a regular string. + /// + /// SAM/BAM has a distinction between regular strings and "Hex format" + /// strings. However, they are both manipulated in C++ via std::string. Thus + /// this modifier can be used to indicate that a tag's string data should be + /// interpreted as "Hex format" rather than a regular, literal string. + /// + HEX_STRING +}; + +/// \brief The Tag class represents a SAM/BAM record tag value. +/// +/// SAM/BAM tags may store values from a variety of types: varying fixed-width +/// integers, strings, arrays of data, etc. +/// +/// The Tag class allow tags to be handled in a generic fashion, while +/// maintaining a high level of type-safety. Only those types recognized by the +/// SAM/BAM format are allowed, and extracting the value from a tag is subject +/// to allowed conversion rules, as well. +/// +// Inspired by (but greatly simplified & modified from) the boost::variant +// wrapper approach taken by DynamicCpp (https://code.google.com/p/dynamic-cpp) +// +class PBBAM_EXPORT Tag +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates a Tag from a signed 8-bit integer or character. + /// + /// Without a TagModifier, the resulting Tag will be annotated as containing + /// an 8-bit integer, whether the input \p value was an integer or a char. + /// For ASCII tags, use one of these methods: + /// \include code/Tag_AsciiCtor.txt + /// + Tag(int8_t value); + + /// \brief Creates a Tag from a signed 8-bit integer or character, + /// applying the provided modifier. + /// + /// This method allows direct construction of an ASCII character, rather + /// than an 8-bit integer (e.g. Tag('A', TagModifier::ASCII_CHAR) ). + /// + /// \throws runtime_error if \p modifier is not valid for int8_t data + /// + Tag(int8_t value, const TagModifier mod); + + /// \brief Creates a Tag from an unsigned 8-bit integer or character. + /// + /// Without a TagModifier, the resulting Tag will be annotated as containing + /// an 8-bit unsigned integer, whether the input \p value was an integer or + /// a char. For ASCII tags, use one of these methods: + /// \include code/Tag_AsciiCtor.txt + /// + Tag(uint8_t value); + + /// \brief Creates a Tag from 16-bit integer. + Tag(int16_t value); + + /// \brief Creates a Tag from 16-bit unsigned integer. + Tag(uint16_t value); + + /// \brief Creates a Tag from 32-bit signed integer. + Tag(int32_t value); + + /// \brief Creates a Tag from 32-bit unsigned integer. + Tag(uint32_t value); + + /// \brief Creates a Tag from floating-point value. + Tag(float value); + + /// \brief Creates a Tag from string data. + Tag(std::string value); + + /// \brief Creates a Tag from string data, adding modifier. + /// + /// \throws runtime_error if \p modifier is not valid for string data + /// + Tag(std::string value, TagModifier mod); + + /// \brief Creates a Tag from a vector of 8-bit integers. + Tag(std::vector value); + + /// \brief Creates a Tag from a vector of 8-bit unsigned integers. + Tag(std::vector value); + + /// \brief Creates a Tag from a vector of 16-bit integers. + Tag(std::vector value); + + /// \brief Creates a Tag from a vector of 16-bit unsigned integers. + Tag(std::vector value); + + /// Constructs a Tag from a vector of 32-bit integers. + Tag(std::vector value); + + /// \brief Creates a Tag from a vector of 32-bit unsigned integers. + Tag(std::vector value); + + /// \brief Creates a Tag from a vector of floating-point values. + Tag(std::vector value); + + Tag() = default; + + Tag& operator=(boost::blank value); + Tag& operator=(int8_t value); + Tag& operator=(uint8_t value); + Tag& operator=(int16_t value); + Tag& operator=(uint16_t value); + Tag& operator=(int32_t value); + Tag& operator=(uint32_t value); + Tag& operator=(float value); + Tag& operator=(std::string value); + Tag& operator=(std::vector value); + Tag& operator=(std::vector value); + Tag& operator=(std::vector value); + Tag& operator=(std::vector value); + Tag& operator=(std::vector value); + Tag& operator=(std::vector value); + Tag& operator=(std::vector value); + + bool operator==(const Tag& other) const; + bool operator!=(const Tag& other) const; + + /// \} + +public: + /// \name Data Conversion & Validation + /// \{ + + /// \brief Converts the tag value to an ASCII character. + /// + /// Tag must hold an integral type, within the valid ASCII range [33-127]. + /// + /// \returns ASCII character value + /// \throws std::runtime_error if not ASCII-compatible + /// + char ToAscii() const; + + /// \returns tag data as signed 8-bit (casting if needed) + /// \throws std::runtime_error if not integral data, or out of valid range + int8_t ToInt8() const; + + /// \returns tag data as unsigned 8-bit (casting if needed) + /// \throws std::runtime_error if not integral data, or out of valid range + uint8_t ToUInt8() const; + + /// \returns tag data as signed 16-bit (casting if needed) + /// \throws std::runtime_error if not integral data, or out of valid range + int16_t ToInt16() const; + + /// \returns tag data as unsigned 16-bit (casting if needed) + /// \throws std::runtime_error if not integral data, or out of valid range + uint16_t ToUInt16() const; + + /// \returns tag data as signed 32-bit (casting if needed) + /// \throws std::runtime_error if not integral data, or out of valid range + int32_t ToInt32() const; + + /// \returns tag data as unsigned 32-bit (casting if needed) + /// \throws std::runtime_error if not integral data, or out of valid range + uint32_t ToUInt32() const; + + /// \returns tag data as float + /// \throws std::runtime_error if tag does not contain a value of + /// explicit type: float + float ToFloat() const; + + /// \returns tag data as std::string + /// \throws std::runtime_error if tag does not contain a value of explicit + /// type: std::string + std::string ToString() const; + + /// \returns tag data as std::vector + /// \throws std::runtime_error if tag does not contain a value of explicit + /// type: std::vector + std::vector ToInt8Array() const; + + /// \returns tag data as std::vector + /// \throws std::runtime_error if tag does not contain a value of explicit + /// type: std::vector + std::vector ToUInt8Array() const; + + /// \returns tag data as std::vector + /// \throws std::runtime_error if tag does not contain a value of explicit + /// type: std::vector + std::vector ToInt16Array() const; + + /// \returns tag data as std::vector + /// \throws std::runtime_error if tag does not contain a value of explicit + /// type: std::vector + std::vector ToUInt16Array() const; + + /// \returns tag data as std::vector + /// \throws std::runtime_error if tag does not contain a value of explicit + /// type: std::vector + std::vector ToInt32Array() const; + + /// \returns tag data as std::vector + /// \throws std::runtime_error if tag does not contain a value of explicit + /// type: std::vector + std::vector ToUInt32Array() const; + + /// \returns tag data as std::vector + /// \throws std::runtime_error if tag does not contain a value of explicit + /// type: std::vector + std::vector ToFloatArray() const; + + /// \} + +public: + /// \name Data Conversion & Validation + /// + + /// \returns true if tag is null (e.g. default-constructed) + bool IsNull() const; + + /// \returns true if tag contains a value of type: int8_t + bool IsInt8() const; + + /// \returns true if tag contains a value of type: uint8_t + bool IsUInt8() const; + + /// \returns true if tag contains a value of type: int16_t + bool IsInt16() const; + + /// \returns true if tag contains a value of type: uint16_t + bool IsUInt16() const; + + /// \returns true if tag contains a value of type: int32_t + bool IsInt32() const; + + /// \returns true if tag contains a value of type: uint32_t + bool IsUInt32() const; + + /// \returns true if tag contains a value of type: float + bool IsFloat() const; + + /// \returns true if tag contains a value of type: std::string + bool IsString() const; + + /// \returns true if tag contains a value of type: std::string \b AND has a + /// TagModifier of TagModifier::HEX_STRING + bool IsHexString() const; + + /// \returns true if tag contains a value of type: std::vector + bool IsInt8Array() const; + + /// \returns true if tag contains a value of type: std::vector + bool IsUInt8Array() const; + + /// \returns true if tag contains a value of type: std::vector + bool IsInt16Array() const; + + /// \returns true if tag contains a value of type: std::vector + bool IsUInt16Array() const; + + /// \returns true if tag contains a value of type: std::vector + bool IsInt32Array() const; + + /// \returns true if tag contains a value of type: std::vector + bool IsUInt32Array() const; + + /// \returns true if tag contains a value of type: std::vector + bool IsFloatArray() const; + + /// \returns true if tag contains a value with any signed integer type + bool IsSignedInt() const; + + /// \returns true if tag contains a value with any unsigned integer type + bool IsUnsignedInt() const; + + /// \returns true if tag contains a value with any integer type + bool IsIntegral() const; + + /// \returns true if tag contains a value with any integer or float type + bool IsNumeric() const; + + /// \returns true if tag contains a vector containing signed integers + bool IsSignedArray() const; + + /// \returns true if tag contains a vector containing unsigned integers + bool IsUnsignedArray() const; + + /// \returns true if tag contains a vector containing integers + bool IsIntegralArray() const; + + /// \returns true if tag contains a vector (integers or floats) + bool IsArray() const; + + /// \} + +public: + /// \name Type & Modifier Attributes + /// \{ + + /// \returns enum value for current tag data + TagDataType Type() const; + + /// \returns printable type name for current tag data + std::string Typename() const; + + /// \returns true if tag data modifier \p m is set + bool HasModifier(const TagModifier m) const; + + /// \returns current tag data modifier + TagModifier Modifier() const; + + /// \brief Sets tag data modifier. + /// + /// \param[in] m new modifier value + /// + /// \returns reference to this tag + Tag& Modifier(const TagModifier m); + + /// \} + +private: + // clang-format off + // NOTE - keep this synced with TagDataType enum ordering + using var_t = boost::variant, + std::vector, + std::vector, + std::vector, + std::vector, + std::vector, + std::vector >; + + var_t data_; + TagModifier modifier_ = TagModifier::NONE; + // clang-format on +}; + +} // namespace BAM +} // namespace PacBio + +#endif // TAG_H diff --git a/include/pbbam/TagCollection.h b/include/pbbam/TagCollection.h new file mode 100644 index 0000000..ef3de0a --- /dev/null +++ b/include/pbbam/TagCollection.h @@ -0,0 +1,35 @@ +// File Description +/// \file TagCollection.h +/// \brief Defines the TagCollection class. +// +// Author: Derek Barnett + +#ifndef TAGCOLLECTION_H +#define TAGCOLLECTION_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/Tag.h" + +namespace PacBio { +namespace BAM { + +/// \brief The TagCollection class represents a collection (or "dictionary") of +/// tags. +/// +/// Tags are mapped to their tag name, a 2-character string. +/// +class PBBAM_EXPORT TagCollection : public std::map +{ +public: + /// \returns true if the collection contains a tag with \p name + bool Contains(const std::string& name) const; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // TAGCOLLECTION_H diff --git a/include/pbbam/TextFileReader.h b/include/pbbam/TextFileReader.h new file mode 100644 index 0000000..a053046 --- /dev/null +++ b/include/pbbam/TextFileReader.h @@ -0,0 +1,87 @@ +// File Description +/// \file TextFileReader.h +/// \brief Defines the TextFileReader class. +// +// Author: Derek Barnett + +#ifndef PBBAM_TEXTFILEREADER_H +#define PBBAM_TEXTFILEREADER_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// +/// \brief The TextFileReader class provides line-by-line access to text files. +/// +/// Supports plain text or gzipped (gzip or bgzip). +/// +/// \note This is a general-purpose file reader. For FASTA/FASTQ, use the dedicated +/// FastaReader or FastqReader for better performance. +/// +class TextFileReader : public internal::QueryBase +{ +public: + /// + /// \brief Reads all lines from a text file + /// + /// \param fn filename + /// \return vector of lines + /// + static std::vector ReadAll(const std::string& fn); + +public: + /// + /// \brief TextLineReader + /// + /// \param filename + /// + explicit TextFileReader(std::string filename); + + TextFileReader(TextFileReader&&) noexcept; + TextFileReader& operator=(TextFileReader&&) noexcept; + ~TextFileReader(); + +public: + // + /// \brief GetNext + /// + /// Allows iteration with range-for: + /// \code{cpp} + /// + /// TextFileReader reader{fn}; + /// for (const std::string& line : reader) { + /// // do stuff with line + /// } + /// \endcode + /// + /// or you can iterate 'manually': + /// \code{cpp} + /// + /// TextFileReader reader{fn}; + /// std::string line; + /// while (reader.GetNext(line)) { + /// // do stuff with line + /// } + /// \endcode + /// + /// \param[out] line + /// \return success/failure + /// + bool GetNext(std::string& line) override; + +private: + class TextFileReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PBBAM_TEXTFILEREADER_H diff --git a/include/pbbam/TextFileWriter.h b/include/pbbam/TextFileWriter.h new file mode 100644 index 0000000..5ce62d5 --- /dev/null +++ b/include/pbbam/TextFileWriter.h @@ -0,0 +1,60 @@ + +// File Description +/// \file TextFileWriter.h +/// \brief Defines the TextFileWriter class. +// +// Author: Derek Barnett + +#ifndef PBBAM_TEXTFILEWRITER_H +#define PBBAM_TEXTFILEWRITER_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +/// +/// \brief The TextFileWriter class provides line-by-line writing text files. +/// +/// Supports plain text or gzipped. For explicitly-bgzipped text, use +/// BgzipWriter instead. +/// +/// \note This is a general-purpose file writer. For FASTA/FASTQ, use the +/// dedicated FastaReader/FastqReader or BgzipFastaWriter/BgzipFastaWriter +/// for better performance. +/// +class TextFileWriter +{ +public: + /// + /// \brief TextLineReader + /// + /// \param filename suffix ".gz" indicates gzipped output + /// + explicit TextFileWriter(const std::string& filename); + + TextFileWriter(TextFileWriter&&) noexcept; + TextFileWriter& operator=(TextFileWriter&&) noexcept; + ~TextFileWriter(); + +public: + /// + /// \brief Write + /// + /// + /// \param line + /// + void Write(const std::string& line); + +private: + class TextFileWriterPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PBBAM_TEXTFILEWRITER_H \ No newline at end of file diff --git a/include/pbbam/Unused.h b/include/pbbam/Unused.h new file mode 100644 index 0000000..6b72ff9 --- /dev/null +++ b/include/pbbam/Unused.h @@ -0,0 +1,15 @@ +#ifndef PBBAM_UNUSED_H +#define PBBAM_UNUSED_H + +namespace PacBio { +namespace BAM { + +template +void UNUSED(const T&) +{ +} + +} // namespace BAM +} // namespace PacBio + +#endif // PBBAM_UNUSED_H diff --git a/include/pbbam/Validator.h b/include/pbbam/Validator.h new file mode 100644 index 0000000..a345107 --- /dev/null +++ b/include/pbbam/Validator.h @@ -0,0 +1,155 @@ +// File Description +/// \file Validator.h +/// \brief Defines the Validator class. +// +// Author: Derek Barnett + +#ifndef VALIDATOR_H +#define VALIDATOR_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/exception/ValidationException.h" + +namespace PacBio { +namespace BAM { + +class BamFile; +class BamHeader; +class BamRecord; +class ReadGroupInfo; + +/// \brief The Validator class provides validation for %BAM data. +/// +/// There are 2 ways to use this class. If you are only compared with a quick & +/// dirty, yes/no validation, then you can use the IsValid() methods. This will +/// swallow the specific cause of the failure, but you don't have to catch an +/// exception and handle it in your client code. If you want to know, +/// specifically, what failed, then you can use the Validate*() methods that +/// will throw a ValidationException if the object is invalid. This exception +/// will provide more details as to what failed and why. +/// +/// See documentation for Config.h for details on building pbbam with +/// auto-validation enabled. +/// +class PBBAM_EXPORT Validator +{ +public: + /// \brief Checks that a %BAM file conforms to the %PacBio specification. + /// + /// When \p entireFile is false, this method only checks file metadata. If + /// \p entireFile is true, all records are checked as well. + /// + /// \param[in] file %BAM header to validate + /// \param[in] entireFile check records in addition to metadata + /// \returns true if \p file passes validation checks + /// + /// \sa Validator::ValidateFileMetdata, Validator::ValidateEntireFile + /// + static bool IsValid(const BamFile& file, const bool entireFile); + + /// \brief Checks that a %BAM header conforms to the %PacBio specification. + /// + /// \returns true if \p header passes validation checks + /// + /// \sa Validator::Validate(const BamHeader& header) + /// + static bool IsValid(const BamHeader& header); + + /// \brief Checks that a %BAM read group conforms to the %PacBio + /// specification. + /// + /// \returns true if \p rg passes validation checks + /// + /// \sa Validator::Validate(const ReadGroupInfo& rg) + /// + static bool IsValid(const ReadGroupInfo& rg); + + /// \brief Checks that a %BAM record conforms to the %PacBio specification. + /// + /// \returns true if \p record passes validation checks + /// + /// \sa Validator::Validate(const BamRecord& record) + /// + static bool IsValid(const BamRecord& record); + + Validator() = delete; + + /// \brief Checks that a %BAM file's header conforms to the + /// %PacBio specification. + /// + /// This validation step checks the SAM/%BAM version number, sort order, + /// PacBioBAM version number, and calls Validate(readGroup) internally for + /// all read groups. + /// + /// \param[in] file %BAM header to validate + /// \param[in] maxErrors maximum number of errors to allow before throwing + /// + /// \throws ValidationException if \p header fails validation checks + /// + static void Validate(const BamHeader& header, + const size_t maxErrors = std::numeric_limits::max()); + + /// \brief Checks that a %BAM read group conforms to the %PacBio + /// specification. + /// + /// \param[in] rg %BAM read group to validate + /// \param[in] maxErrors maximum number of errors to allow before throwing + /// + /// \throws ValidationException if \p rg fails validation checks + /// + static void Validate(const ReadGroupInfo& rg, + const size_t maxErrors = std::numeric_limits::max()); + + /// \brief Checks that a %BAM record conforms to the %PacBio specification. + /// + /// \param[in] record %BAM record to validate + /// \param[in] maxErrors maximum number of errors to allow before throwing + /// + /// \throws ValidationException if \p record fails validation checks + /// + static void Validate(const BamRecord& record, + const size_t maxErrors = std::numeric_limits::max()); + + /// \brief Checks that a %BAM file's (entire) contents conform to the + /// %PacBio specification. + /// + /// This is equivalent to: + /// + /// \code + /// Validator::ValidateMetadata(file); + /// EntireFileQuery query(file); + /// for (const BamRecord& record : query) + /// Validator::Validate(record); + /// \endcode + /// + /// \param[in] file %BAM file to validate + /// \param[in] maxErrors maximum number of errors to allow before throwing + /// + /// \throws ValidationException if \p file fails validation checks + /// + static void ValidateEntireFile(const BamFile& file, + const size_t maxErrors = std::numeric_limits::max()); + + /// \brief Checks that a %BAM file's metadata conforms to the + /// %PacBio specification. + /// + /// This validation step checks the filename, ensures EOF marker, and + /// presence of PBI. It also calls Validate(file.Header()) internally. + /// + /// \param[in] file %BAM header to validate + /// \param[in] maxErrors maximum number of errors to allow before throwing + /// + /// \throws ValidationException if \p header fails validation checks + /// + static void ValidateFileMetadata(const BamFile& file, + const size_t maxErrors = std::numeric_limits::max()); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // VALIDATOR_H diff --git a/include/pbbam/ZmwChunkedFastaReader.h b/include/pbbam/ZmwChunkedFastaReader.h new file mode 100644 index 0000000..2ad208b --- /dev/null +++ b/include/pbbam/ZmwChunkedFastaReader.h @@ -0,0 +1,100 @@ +// File Description +/// \file ZmwChunkedFastaReader.h +/// \brief Defines the ZmwChunkedFastaReader class. +// +// Author: Derek Barnett + +#ifndef ZMWCHUNKEDFASTAREADER_H +#define ZMWCHUNKEDFASTAREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/FastaSequence.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// +/// \brief The ZmwChunkedFastaReader provides sequential access to FASTA records, +/// where iteration is bounded by chunks of (unique) ZMWs. +/// +class ZmwChunkedFastaReader : public internal::QueryBase +{ +public: + /// + /// Construct a new ZMW-chunked FASTA reader. + /// + /// \param fn FASTA file, must have a *.fai index + /// \param numChunks desired number of chunks + /// + /// Actual chunk count may be smaller than the requested number, if the input + /// size is smaller. + /// + ZmwChunkedFastaReader(const std::string& fn, const size_t numChunks); + + ZmwChunkedFastaReader(ZmwChunkedFastaReader&&) noexcept; + ZmwChunkedFastaReader& operator=(ZmwChunkedFastaReader&&) noexcept; + ~ZmwChunkedFastaReader(); + + /// + /// \returns the number of chunks available. + /// + /// Actual chunk count may be smaller than the requested number, if the input + /// size is smaller. + /// + size_t NumChunks() const; + + /// + /// Sets current chunk to start iterating over. + /// + ZmwChunkedFastaReader& Chunk(size_t chunkId); + + /// + /// \returns the current chunk in use + /// + size_t Chunk() const; + +public: + /// + /// \brief GetNext + /// + /// Allows iteration with range-for: + /// \code{cpp} + /// + /// ZmwChunkedFastaReader reader{fn, numChunks}; + /// reader.Chunk(4); + /// for (const FastaSequence& seq : reader) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// or you can iterate 'manually': + /// \code{cpp} + /// + /// ZmwChunkedFastaReader reader{fn, numChunks}; + /// reader.Chunk(4); + /// FastaSequence seq; + /// while (reader.GetNext(seq)) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// \param[out] record + /// \return success/failure + /// + bool GetNext(FastaSequence& record); + +private: + class ZmwChunkedFastaReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWCHUNKEDFASTAREADER_H diff --git a/include/pbbam/ZmwChunkedFastqReader.h b/include/pbbam/ZmwChunkedFastqReader.h new file mode 100644 index 0000000..d0d20d9 --- /dev/null +++ b/include/pbbam/ZmwChunkedFastqReader.h @@ -0,0 +1,102 @@ + + +// File Description +/// \file ZmwChunkedFastqReader.h +/// \brief Defines the ZmwChunkedFastqReader class. +// +// Author: Derek Barnett + +#ifndef ZMWCHUNKEDFASTQREADER_H +#define ZMWCHUNKEDFASTQREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/FastqSequence.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// +/// \brief The ZmwChunkedFastqReader provides sequential access to FASTQ records, +/// where iteration is bounded by chunks of (unique) ZMWs. +/// +class ZmwChunkedFastqReader : public internal::QueryBase +{ +public: + /// + /// Construct a new ZMW-chunked FASTQ reader. + /// + /// \param fn FASTQ file, must have a *.fai index + /// \param numChunks desired number of chunks + /// + /// Actual chunk count may be smaller than the requested number, if the input + /// size is smaller. + /// + ZmwChunkedFastqReader(const std::string& fn, const size_t numChunks); + + ZmwChunkedFastqReader(ZmwChunkedFastqReader&&) noexcept; + ZmwChunkedFastqReader& operator=(ZmwChunkedFastqReader&&) noexcept; + ~ZmwChunkedFastqReader(); + + /// + /// \returns the number of chunks available. + /// + /// Actual chunk count may be smaller than the requested number, if the input + /// size is smaller. + /// + size_t NumChunks() const; + + /// + /// Sets current chunk to start iterating over. + /// + ZmwChunkedFastqReader& Chunk(size_t chunkId); + + /// + /// \returns the current chunk in use + /// + size_t Chunk() const; + +public: + /// + /// \brief GetNext + /// + /// Allows iteration with range-for: + /// \code{cpp} + /// + /// ZmwChunkedFastqReader reader{fn, numChunks}; + /// reader.Chunk(4); + /// for (const FastqSequence& seq : reader) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// or you can iterate 'manually': + /// \code{cpp} + /// + /// ZmwChunkedFastqReader reader{fn, numChunks}; + /// reader.Chunk(4); + /// FastqSequence seq; + /// while (reader.GetNext(seq)) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// \param[out] record + /// \return success/failure + /// + bool GetNext(FastqSequence& record); + +private: + class ZmwChunkedFastqReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWCHUNKEDFASTQREADER_H diff --git a/include/pbbam/ZmwGroupQuery.h b/include/pbbam/ZmwGroupQuery.h new file mode 100644 index 0000000..c708e0f --- /dev/null +++ b/include/pbbam/ZmwGroupQuery.h @@ -0,0 +1,62 @@ +// File Description +/// \file ZmwGroupQuery.h +/// \brief Defines the ZmwGroupQuery class. +// +// Author: Derek Barnett + +#ifndef ZMWGROUPQUERY_H +#define ZMWGROUPQUERY_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The ZmwGroupQuery class provides iterable access to a DataSet's +/// %BAM records, limiting results to those matching a ZMW hole number +/// whitelist, and grouping those results by hole number. +/// +/// Example: +/// \include code/ZmwGroupQuery.txt +/// +/// \note Currently, all %BAM files must have a corresponding ".pbi" index file. +/// Use BamFile::EnsurePacBioIndexExists before creating the query if one +/// may not be present. +/// +class PBBAM_EXPORT ZmwGroupQuery : public internal::IGroupQuery +{ +public: + /// \brief Creates a new ZmwGroupQuery, limiting record results to only + /// those matching a ZMW hole number criterion. + /// + /// \param[in] zmwWhitelist vector of allowed ZMW hole numbers + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or + /// PBI files. + /// + ZmwGroupQuery(const std::vector& zmwWhitelist, const DataSet& dataset); + ~ZmwGroupQuery(); + +public: + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(std::vector& records) override; + +private: + class ZmwGroupQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWGROUPQUERY_H diff --git a/include/pbbam/ZmwQuery.h b/include/pbbam/ZmwQuery.h new file mode 100644 index 0000000..37ee529 --- /dev/null +++ b/include/pbbam/ZmwQuery.h @@ -0,0 +1,62 @@ +// File Description +/// \file ZmwQuery.h +/// \brief Defines the ZmwQuery class. +// +// Author: Derek Barnett + +#ifndef ZMWQUERY_H +#define ZMWQUERY_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// \brief The ZmwQuery class provides iterable access to a DataSet's +/// %BAM records, limiting results to those matching a ZMW hole number +/// whitelist. +/// +/// Example: +/// \include code/ZmwQuery.txt +/// +/// \note Currently, all %BAM files must have a corresponding ".pbi" index file. +/// Use BamFile::EnsurePacBioIndexExists before creating the query if one +/// may not be present. +/// +class PBBAM_EXPORT ZmwQuery : public internal::IQuery +{ +public: + /// \brief Creates a new ZmwQuery, limiting record results to only + /// those matching a ZMW hole number criterion. + /// + /// \param[in] zmwWhitelist vector of allowed ZMW hole numbers + /// \param[in] dataset input data source(s) + /// + /// \throws std::runtime_error on failure to open/read underlying %BAM or + /// PBI files. + /// + ZmwQuery(std::vector zmwWhitelist, const DataSet& dataset); + + ~ZmwQuery(); + + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(BamRecord& r) override; + +private: + class ZmwQueryPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWQUERY_H diff --git a/include/pbbam/ZmwType.h b/include/pbbam/ZmwType.h new file mode 100644 index 0000000..6447cc7 --- /dev/null +++ b/include/pbbam/ZmwType.h @@ -0,0 +1,28 @@ +// File Description +/// \file ZmwType.h +/// \brief Defines the ZmwType enum. +// +// Author: Armin Töpfer + +#ifndef ZMWTYPE_H +#define ZMWTYPE_H + +#include "pbbam/Config.h" + +namespace PacBio { +namespace BAM { + +/// \brief This enum defines the different ZMW categories of scraps +/// +enum class ZmwType : char +{ + CONTROL = 'C', + MALFORMED = 'M', + NORMAL = 'N', + SENTINEL = 'S' +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWTYPE_H diff --git a/include/pbbam/ZmwTypeMap.h b/include/pbbam/ZmwTypeMap.h new file mode 100644 index 0000000..3e0fffa --- /dev/null +++ b/include/pbbam/ZmwTypeMap.h @@ -0,0 +1,31 @@ +// File Description +/// \file ZmwTypeMap.h +/// \brief Defines the ZmwTypeMap class. +// +// Author: Armin Töpfer + +#ifndef ZMWTYPEMAP_H +#define ZMWTYPEMAP_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/ZmwType.h" + +namespace PacBio { +namespace BAM { + +/// \brief The ZmwTypeMap class provides mapping between char codes and +/// ZmwType enum keys. +/// +class ZmwTypeMap +{ +public: + static std::map ParseChar; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWTYPEMAP_H diff --git a/include/pbbam/bed/BedReader.h b/include/pbbam/bed/BedReader.h new file mode 100644 index 0000000..fdfad8c --- /dev/null +++ b/include/pbbam/bed/BedReader.h @@ -0,0 +1,86 @@ +// File Description +/// \file BedReader.h +/// \brief Defines the BedReader class. +// +// Author: Derek Barnett + +#ifndef PBBAM_BED_BEDREADER_H +#define PBBAM_BED_BEDREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/GenomicInterval.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { + +/// +/// \brief The BedReader provides sequential access to BED records. +/// +/// Supports plain text or gzipped (gzip or bgzip). +/// +class BedReader : public internal::QueryBase +{ +public: + /// + /// \brief Reads all BED intervals from a file + /// + /// \param fn BED filename + /// \return vector of intervals + /// + static std::vector ReadAll(const std::string& fn); + +public: + /// \name Constructors & Related Methods + /// \{ + + explicit BedReader(const std::string& fn); + + BedReader(BedReader&&) noexcept; + BedReader& operator=(BedReader&&) noexcept; + ~BedReader(); + + /// \} + +public: + /// + /// \brief GetNext + /// + /// Allows iteration with range-for: + /// \code{cpp} + /// + /// BedReader reader{fn}; + /// for (const auto& interval : reader) { + /// // do stuff with seq + /// } + /// \endcode + /// + /// or you can iterate 'manually': + /// \code{cpp} + /// + /// BedReader reader{fn}; + /// GenomicInterval interval; + /// while (reader.GetNext(interval)) { + /// // do stuff with interval + /// } + /// \endcode + /// + /// \param[out] record + /// \return success/failure + /// + bool GetNext(GenomicInterval& interval); + +private: + class BedReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // PBBAM_BED_BEDREADER_H diff --git a/include/pbbam/bed/BedWriter.h b/include/pbbam/bed/BedWriter.h new file mode 100644 index 0000000..1b0b1fd --- /dev/null +++ b/include/pbbam/bed/BedWriter.h @@ -0,0 +1,42 @@ +// File Description +/// \file BedWriter.h +/// \brief Defines the BedWriter class. +// +// Author: Derek Barnett + +#ifndef PBBAM_BEDWRITER_H +#define PBBAM_BEDWRITER_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace Data { + +class GenomicInterval; +} + +namespace BAM { + +class BedWriter +{ +public: + explicit BedWriter(const std::string& fn); + + BedWriter(BedWriter&&) noexcept; + BedWriter& operator=(BedWriter&&) noexcept; + ~BedWriter(); + +public: + void Write(const Data::GenomicInterval& interval); + +private: + class BedWriterPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FASTQWRITER_H diff --git a/include/pbbam/ccs/CCSHeader.h b/include/pbbam/ccs/CCSHeader.h new file mode 100644 index 0000000..22835f9 --- /dev/null +++ b/include/pbbam/ccs/CCSHeader.h @@ -0,0 +1,25 @@ +// Author: Derek Barnett + +#ifndef PBBAM_CCS_CCSHEADER_H +#define PBBAM_CCS_CCSHEADER_H + +#include "pbbam/Config.h" + +#include + +namespace PacBio { +namespace CCS { + +struct CCSHeader +{ + std::string MovieName; + std::string BindingKit; + std::string SequencingKit; + std::string BasecallerVersion; + std::string FrameRate; +}; + +} // namespace CCS +} // namespace PacBio + +#endif // PBBAM_CCS_CCSHEADER_H diff --git a/include/pbbam/ccs/CCSPbiBuilder.h b/include/pbbam/ccs/CCSPbiBuilder.h new file mode 100644 index 0000000..f733a24 --- /dev/null +++ b/include/pbbam/ccs/CCSPbiBuilder.h @@ -0,0 +1,54 @@ +#ifndef PBBAM_CCS_CCSPBIBUILDER_H +#define PBBAM_CCS_CCSPBIBUILDER_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/PbiBuilder.h" +#include "pbbam/ccs/CCSHeader.h" +#include "pbbam/ccs/CCSRecord.h" + +namespace PacBio { +namespace CCS { + +struct CCSHeader; +struct CCSRecord; + +struct CCSPbiBuilderConfig +{ + using PbiBuilder = PacBio::BAM::PbiBuilder; + + // zlib compression level for PBI file + PbiBuilder::CompressionLevel CompressionLevel = PbiBuilder::DefaultCompression; + + // Number of threads to use in PBI file compression. Only active during + // CCSPbiBuilder::Close(). + size_t NumThreads = 4; +}; + +class CCSPbiBuilder +{ +public: +public: + CCSPbiBuilder(const std::string& pbiFilename, const std::string& movieName, + const CCSPbiBuilderConfig& config = CCSPbiBuilderConfig()); + CCSPbiBuilder(const std::string& pbiFilename, const CCSHeader& header, + const CCSPbiBuilderConfig& config = CCSPbiBuilderConfig()); + ~CCSPbiBuilder(); + +public: + void AddRecord(const CCSRecord& record); + void Close(); + const std::string& MovieName() const; + +private: + class CCSPbiBuilderPrivate; + std::unique_ptr d_; +}; + +} // namespace CCS +} // namespace PacBio + +#endif // PBBAM_CCS_CCSPBIBUILDER_H diff --git a/include/pbbam/ccs/CCSRecord.h b/include/pbbam/ccs/CCSRecord.h new file mode 100644 index 0000000..85be3dd --- /dev/null +++ b/include/pbbam/ccs/CCSRecord.h @@ -0,0 +1,40 @@ +// Author: Derek Barnett + +#ifndef PBBAM_CCS_CCSRECORD_H +#define PBBAM_CCS_CCSRECORD_H + +#include "pbbam/Config.h" + +#include "pbbam/Accuracy.h" +#include "pbbam/Frames.h" +#include "pbbam/LocalContextFlags.h" +#include "pbbam/Position.h" +#include "pbbam/SNR.h" + +namespace PacBio { +namespace CCS { + +struct CCSRecord +{ + int32_t HoleNumber = 0; + + PacBio::BAM::Position QueryStart = 0; + + PacBio::BAM::Position QueryEnd = 0; + + PacBio::BAM::LocalContextFlags LocalContextFlags = + PacBio::BAM::LocalContextFlags::NO_LOCAL_CONTEXT; + + PacBio::BAM::Accuracy Accuracy = 0.0f; + + PacBio::Data::SNR SignalToNoise = {0.0, 0.0, 0.0, 0.0}; + + std::string Sequence; + + PacBio::BAM::Frames PulseWidths; +}; + +} // namespace CCS +} // namespace PacBio + +#endif // PBBAM_CCS_CCSRECORD_H diff --git a/include/pbbam/ccs/CCSRecordFormat.h b/include/pbbam/ccs/CCSRecordFormat.h new file mode 100644 index 0000000..123491a --- /dev/null +++ b/include/pbbam/ccs/CCSRecordFormat.h @@ -0,0 +1,29 @@ +#ifndef PBBAM_CCS_CCSRECORDFORMAT_H +#define PBBAM_CCS_CCSRECORDFORMAT_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/ccs/CCSHeader.h" +#include "pbbam/ccs/CCSRecord.h" + +namespace PacBio { +namespace CCS { + +struct CCSRecordFormat +{ + // header + static CCSHeader DeserializeHeader(const std::vector& lines); + static std::vector SerializeHeader(const CCSHeader& header); + + // record + static CCSRecord DeserializeRecord(const std::string& line); + static std::string SerializeRecord(const CCSRecord& record); +}; + +} // namespace CCS +} // namespace PacBio + +#endif // PBBAM_CCS_CCSRECORDFORMAT_H diff --git a/include/pbbam/ccs/CCSRecordReader.h b/include/pbbam/ccs/CCSRecordReader.h new file mode 100644 index 0000000..cc77491 --- /dev/null +++ b/include/pbbam/ccs/CCSRecordReader.h @@ -0,0 +1,42 @@ +// Author: Derek Barnett + +#ifndef PBBAM_CCS_CCSRECORDREADER_H +#define PBBAM_CCS_CCSRECORDREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/ccs/CCSHeader.h" +#include "pbbam/ccs/CCSRecord.h" +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace CCS { + +/// +/// Reads CCSRecords from stdin +// +class CCSRecordReader : public PacBio::BAM::internal::QueryBase +{ +public: + CCSRecordReader(); + CCSRecordReader(std::istream& in); + ~CCSRecordReader(); + +public: + const CCSHeader& Header() const; + + bool GetNext(CCSRecord& record); + +private: + class CCSRecordReaderPrivate; + std::unique_ptr d_; +}; + +} // namespace CCS +} // namespace PacBio + +#endif // PBBAM_CCS_CCSRECORD_H diff --git a/include/pbbam/ccs/CCSRecordWriter.h b/include/pbbam/ccs/CCSRecordWriter.h new file mode 100644 index 0000000..0e6edfe --- /dev/null +++ b/include/pbbam/ccs/CCSRecordWriter.h @@ -0,0 +1,50 @@ +#ifndef PBBAM_CCS_CCSRECORDWRITER_H +#define PBBAM_CCS_CCSRECORDWRITER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/ccs/CCSHeader.h" +#include "pbbam/ccs/CCSRecord.h" + +namespace PacBio { +namespace CCS { + +/// +/// Writes CCSRecords to stdout +/// +class CCSRecordWriter +{ +public: + /// + /// \brief Construct a new CCSRecordWriter object + /// + /// \param header + /// + CCSRecordWriter(const CCSHeader& header); + + CCSRecordWriter(const CCSHeader& header, std::ostream& out); + + ~CCSRecordWriter(); + + /// + /// \brief + /// + /// \param record + /// \return true + /// \return false + /// + void Write(const CCSRecord& record); + +private: + class CCSRecordWriterPrivate; + std::unique_ptr d_; +}; + +} // namespace CCS +} // namespace PacBio + +#endif // PBBAM_CCS_CCSRECORDWRITER_H diff --git a/include/pbbam/exception/BundleChemistryMappingException.h b/include/pbbam/exception/BundleChemistryMappingException.h new file mode 100644 index 0000000..1a45754 --- /dev/null +++ b/include/pbbam/exception/BundleChemistryMappingException.h @@ -0,0 +1,45 @@ +// File Description +/// \file BundleChemistryMappingException.h +/// \brief Defines the BundleChemistryMappingException class. +// +// Author: Derek Barnett, Lance Hepler + +#ifndef BUNDLECHEMISTRYMAPPINGEXCEPTION_H +#define BUNDLECHEMISTRYMAPPINGEXCEPTION_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +/// \brief The BundleChemistryMappingException class represents an exception +/// that will be thrown when an invalid sequencing chemistry combination +/// is encountered. +/// +class BundleChemistryMappingException : public std::exception +{ +public: + BundleChemistryMappingException(std::string mappingXml, std::string msg) + : mappingXml_(std::move(mappingXml)) + , what_(std::string("invalid ") + mappingXml_ + ": " + std::move(msg)) + { + } + + // This is a work around for the Intel PHI compiler (icpc) + ~BundleChemistryMappingException() throw() {} + +public: + const char* what() const noexcept override { return what_.c_str(); } + +protected: + std::string mappingXml_; + std::string what_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // BUNDLECHEMISTRYMAPPINGEXCEPTION_H diff --git a/include/pbbam/exception/InvalidSequencingChemistryException.h b/include/pbbam/exception/InvalidSequencingChemistryException.h new file mode 100644 index 0000000..0836f38 --- /dev/null +++ b/include/pbbam/exception/InvalidSequencingChemistryException.h @@ -0,0 +1,63 @@ +// File Description +/// \file InvalidSequencingChemistryException.h +/// \brief Defines the InvalidSequencingChemistryException class. +// +// Author: Derek Barnett + +#ifndef INVALIDSEQUENCINGCHEMISTRYEXCEPTION_H +#define INVALIDSEQUENCINGCHEMISTRYEXCEPTION_H + +#include "pbbam/Config.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { + +/// \brief The InvalidSequencingChemistryException class represents an exception +/// that will be thrown when an invalid sequencing chemistry combination +/// is encountered. +/// +class InvalidSequencingChemistryException : public std::exception +{ +public: + InvalidSequencingChemistryException(std::string bindingKit, std::string sequencingKit, + std::string basecallerVersion) + : bindingKit_(std::move(bindingKit)) + , sequencingKit_(std::move(sequencingKit)) + , basecallerVersion_(std::move(basecallerVersion)) + { + std::ostringstream s; + s << "unsupported sequencing chemistry combination:\n" + << " binding kit: " << bindingKit_ << '\n' + << " sequencing kit: " << sequencingKit_ << '\n' + << " basecaller version: " << basecallerVersion_ << '\n'; + what_ = s.str(); + } + + // This is a work around for the Intel PHI compiler (icpc) + ~InvalidSequencingChemistryException() throw() {} + +public: + const std::string& BindingKit() const { return bindingKit_; } + + const std::string& SequencingKit() const { return sequencingKit_; } + + const std::string& BasecallerVersion() const { return basecallerVersion_; } + +public: + const char* what() const noexcept override { return what_.c_str(); } + +protected: + std::string bindingKit_; + std::string sequencingKit_; + std::string basecallerVersion_; + std::string what_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // INVALIDSEQUENCINGCHEMISTRYEXCEPTION_H diff --git a/include/pbbam/exception/ValidationException.h b/include/pbbam/exception/ValidationException.h new file mode 100644 index 0000000..804f135 --- /dev/null +++ b/include/pbbam/exception/ValidationException.h @@ -0,0 +1,60 @@ +// File Description +/// \file ValidationException.h +/// \brief Defines the ValidationException class. +// +// Author: Derek Barnett + +#ifndef VALIDATIONEXCEPTION_H +#define VALIDATIONEXCEPTION_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +/// \brief The ValidationExecption represents an exception that will be thrown +/// when any error is encountered using the Validator API. In addition to +/// a default display message, it provides programmatic access to all +/// reported error messages. +/// +/// \sa Validator::Validate(const BamRecord& record) +/// +class ValidationException : public std::runtime_error +{ +public: + using ErrorList = std::vector; + using ErrorMap = std::map; + +public: + ValidationException(ErrorMap fileErrors, ErrorMap readGroupErrors, ErrorMap recordErrors); + + // This is a work around for the Intel PHI compiler (icpc) + ~ValidationException() throw() {} + +public: + const ErrorMap& FileErrors() const; + const ErrorMap& ReadGroupErrors() const; + const ErrorMap& RecordErrors() const; + + const char* what() const noexcept override; + +private: + ErrorMap fileErrors_; + ErrorMap readGroupErrors_; + ErrorMap recordErrors_; + std::string msg_; + +private: + void FormatMessage(); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // VALIDATIONEXCEPTION_H diff --git a/include/pbbam/internal/Compare.inl b/include/pbbam/internal/Compare.inl new file mode 100644 index 0000000..663556f --- /dev/null +++ b/include/pbbam/internal/Compare.inl @@ -0,0 +1,43 @@ +// File Description +/// \file Compare.inl +/// \brief Inline implementations for the Compare class & inner classes. +// +// Author: Derek Barnett + +#include "pbbam/Compare.h" + +namespace PacBio { +namespace BAM { +namespace internal { + +template struct MemberFnProxy; + +template +struct MemberFnProxy +{ + static R call(const T& obj, Args&&... args) + { + return (obj.*fn)(std::forward(args)...); + } +}; + +} // namespace internal + +template::MemberFnType fn, + typename CompareType> +inline bool Compare::MemberFunctionBase::operator()(const BamRecord& lhs, + const BamRecord& rhs) const +{ + using MemberFnTypeImpl = typename Compare::MemberFunctionBaseHelper::MemberFnType; + using Proxy = internal::MemberFnProxy; + + CompareType cmp; + return cmp(Proxy::call(lhs), Proxy::call(rhs)); +} + +inline bool Compare::None::operator()(const BamRecord&, const BamRecord&) const +{ return false; } + +} // namespace BAM +} // namespace PacBio diff --git a/include/pbbam/internal/CompositeBamReader.inl b/include/pbbam/internal/CompositeBamReader.inl new file mode 100644 index 0000000..fcc6ab5 --- /dev/null +++ b/include/pbbam/internal/CompositeBamReader.inl @@ -0,0 +1,360 @@ +// File Description +/// \file CompositeBamReader.inl +/// \brief Inline implementations for the composite BAM readers, for +/// working with multiple input files. +// +// Author: Derek Barnett + +#include "pbbam/CompositeBamReader.h" + +#include +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { +namespace internal { + +// ----------------------------------- +// Merging helpers +// ----------------------------------- + +inline CompositeMergeItem::CompositeMergeItem(std::unique_ptr rdr) + : reader{std::move(rdr)} +{ +} + +inline CompositeMergeItem::CompositeMergeItem(std::unique_ptr rdr, BamRecord rec) + : reader{std::move(rdr)}, record{std::move(rec)} +{ +} + +template +inline bool CompositeMergeItemSorter::operator()(const CompositeMergeItem& lhs, + const CompositeMergeItem& rhs) const +{ + const auto& l = lhs.record; + const auto& r = rhs.record; + return CompareType()(l, r); +} + +} // namespace internal + +// ----------------------------------- +// GenomicIntervalCompositeBamReader +// ----------------------------------- + +inline GenomicIntervalCompositeBamReader::GenomicIntervalCompositeBamReader( + const std::vector& bamFiles) + : GenomicIntervalCompositeBamReader{bamFiles, MakeBaiIndexCache(bamFiles)} +{ +} + +inline GenomicIntervalCompositeBamReader::GenomicIntervalCompositeBamReader( + const std::vector& bamFiles, const BaiIndexCache& cache) +{ + indexCache_ = cache; + + filenames_.reserve(bamFiles.size()); + for (const auto& bamFile : bamFiles) + filenames_.push_back(bamFile.Filename()); +} + +inline GenomicIntervalCompositeBamReader::GenomicIntervalCompositeBamReader(const DataSet& dataset) + : GenomicIntervalCompositeBamReader{dataset.BamFiles()} +{ +} + +inline GenomicIntervalCompositeBamReader::GenomicIntervalCompositeBamReader( + const DataSet& dataset, const BaiIndexCache& cache) + : GenomicIntervalCompositeBamReader{dataset.BamFiles(), cache} +{ +} + +inline GenomicIntervalCompositeBamReader::GenomicIntervalCompositeBamReader( + const GenomicInterval& interval, const std::vector& bamFiles) + : GenomicIntervalCompositeBamReader{interval, bamFiles, MakeBaiIndexCache(bamFiles)} +{ +} + +inline GenomicIntervalCompositeBamReader::GenomicIntervalCompositeBamReader( + const GenomicInterval& interval, const std::vector& bamFiles, + const BaiIndexCache& cache) + : GenomicIntervalCompositeBamReader{bamFiles, cache} +{ + Interval(interval); +} + +inline GenomicIntervalCompositeBamReader::GenomicIntervalCompositeBamReader( + const GenomicInterval& interval, const DataSet& dataset) + : GenomicIntervalCompositeBamReader{interval, dataset.BamFiles()} +{ +} + +inline GenomicIntervalCompositeBamReader::GenomicIntervalCompositeBamReader( + const GenomicInterval& interval, const DataSet& dataset, const BaiIndexCache& cache) + : GenomicIntervalCompositeBamReader{interval, dataset.BamFiles(), cache} +{ +} + +inline bool GenomicIntervalCompositeBamReader::GetNext(BamRecord& record) +{ + // nothing left to read + if (mergeItems_.empty()) return false; + + // non-destructive 'pop' of first item from queue + auto firstIter = mergeItems_.begin(); + auto firstItem = + internal::CompositeMergeItem{std::move(firstIter->reader), std::move(firstIter->record)}; + mergeItems_.pop_front(); + + // store its record in our output record + std::swap(record, firstItem.record); + + // try fetch 'next' from first item's reader + // if successful, re-insert it into container & re-sort on our new values + // otherwise, this item will go out of scope & reader destroyed + if (firstItem.reader->GetNext(firstItem.record)) { + mergeItems_.push_front(std::move(firstItem)); + UpdateSort(); + } + + // return success + return true; +} + +inline const GenomicInterval& GenomicIntervalCompositeBamReader::Interval() const +{ + return interval_; +} + +inline GenomicIntervalCompositeBamReader& GenomicIntervalCompositeBamReader::Interval( + const GenomicInterval& interval) +{ + // reset readers + mergeItems_.clear(); + + // create readers for files + std::deque updatedMergeItems; + std::vector missingBai; + for (size_t i = 0; i < filenames_.size(); ++i) { + const BamFile bamFile{filenames_.at(i)}; + if (bamFile.StandardIndexExists()) { + internal::CompositeMergeItem item{std::unique_ptr{ + new BaiIndexedBamReader{interval, std::move(bamFile), indexCache_->at(i)}}}; + if (item.reader->GetNext(item.record)) updatedMergeItems.push_back(std::move(item)); + // else not an error, simply no data matching interval + } else { + // maybe handle PBI-backed interval searches if BAI missing, but for now treat as error + missingBai.push_back(bamFile.Filename()); + } + } + + // throw if any files missing BAI + if (!missingBai.empty()) { + std::ostringstream e; + e << "GenomicIntervalCompositeBamReader: failed to open because the following files are " + "missing a *.bai index:\n"; + for (const auto& fn : missingBai) + e << " " << fn << '\n'; + throw std::runtime_error{e.str()}; + } + + // update our actual container and return + mergeItems_ = std::move(updatedMergeItems); + UpdateSort(); + return *this; +} + +struct OrderByPosition +{ + static inline bool less_than(const BamRecord& lhs, const BamRecord& rhs) + { + const int32_t lhsId = lhs.ReferenceId(); + const int32_t rhsId = rhs.ReferenceId(); + if (lhsId == -1) return false; + if (rhsId == -1) return true; + + if (lhsId == rhsId) + return lhs.ReferenceStart() < rhs.ReferenceStart(); + else + return lhsId < rhsId; + } + + static inline bool equals(const BamRecord& lhs, const BamRecord& rhs) + { + return lhs.ReferenceId() == rhs.ReferenceId() && + lhs.ReferenceStart() == rhs.ReferenceStart(); + } +}; + +struct PositionSorter + : std::binary_function +{ + bool operator()(const internal::CompositeMergeItem& lhs, + const internal::CompositeMergeItem& rhs) const + { + const BamRecord& l = lhs.record; + const BamRecord& r = rhs.record; + return OrderByPosition::less_than(l, r); + } +}; + +inline void GenomicIntervalCompositeBamReader::UpdateSort() +{ + std::sort(mergeItems_.begin(), mergeItems_.end(), PositionSorter{}); +} + +// ------------------------------ +// PbiRequestCompositeBamReader +// ------------------------------ + +template +inline PbiFilterCompositeBamReader::PbiFilterCompositeBamReader( + const PbiFilter& filter, const std::vector& bamFiles) + : PbiFilterCompositeBamReader{filter, bamFiles, MakePbiIndexCache(bamFiles)} +{ +} + +template +inline PbiFilterCompositeBamReader::PbiFilterCompositeBamReader( + const PbiFilter& filter, const std::vector& bamFiles, const PbiIndexCache& cache) + : indexCache_{cache}, numReads_{0} +{ + filenames_.reserve(bamFiles.size()); + for (const auto& bamFile : bamFiles) + filenames_.push_back(bamFile.Filename()); + Filter(filter); +} + +template +inline PbiFilterCompositeBamReader::PbiFilterCompositeBamReader( + const PbiFilter& filter, const DataSet& dataset) + : PbiFilterCompositeBamReader{filter, dataset.BamFiles()} +{ +} + +template +inline PbiFilterCompositeBamReader::PbiFilterCompositeBamReader( + const PbiFilter& filter, const DataSet& dataset, const PbiIndexCache& cache) + : PbiFilterCompositeBamReader{filter, dataset.BamFiles(), cache} +{ +} + +template +inline bool PbiFilterCompositeBamReader::GetNext(BamRecord& record) +{ + // nothing left to read + if (mergeQueue_.empty()) return false; + + // non-destructive 'pop' of first item from queue + auto firstIter = mergeQueue_.begin(); + value_type firstItem{std::move(firstIter->reader), std::move(firstIter->record)}; + mergeQueue_.pop_front(); + + // store its record in our output record + std::swap(record, firstItem.record); + + // try fetch 'next' from first item's reader + // if successful, re-insert it into container & re-sort on our new values + // otherwise, this item will go out of scope & reader destroyed + if (firstItem.reader->GetNext(firstItem.record)) { + mergeQueue_.push_front(std::move(firstItem)); + UpdateSort(); + } + + // return success + return true; +} + +template +inline PbiFilterCompositeBamReader& PbiFilterCompositeBamReader::Filter( + const PbiFilter& filter) +{ + // std::cerr << "PbiFilterCompositeBamReader::Filter()\n"; + + // reset reader queue + mergeQueue_.clear(); + + // create readers for files + container_type updatedMergeItems; + std::vector missingPbi; + for (size_t i = 0; i < filenames_.size(); ++i) { + const BamFile bamFile{filenames_.at(i)}; + if (bamFile.PacBioIndexExists()) { + auto item = internal::CompositeMergeItem{std::unique_ptr{ + new PbiIndexedBamReader{filter, std::move(bamFile), indexCache_->at(i)}}}; + if (item.reader->GetNext(item.record)) updatedMergeItems.push_back(std::move(item)); + // else not an error, simply no data matching filter + } else + missingPbi.push_back(filenames_.at(i)); + } + + // throw if any files missing PBI + if (!missingPbi.empty()) { + std::ostringstream e; + e << "PbiFilterCompositeBamReader: failed to open because the following files are " + "missing a *.pbi index:\n"; + for (const auto& fn : missingPbi) + e << " " << fn << '\n'; + throw std::runtime_error{e.str()}; + } + + // update our actual container, store num matching reads, sort & and return + mergeQueue_ = std::move(updatedMergeItems); + numReads_ = 0; + for (const auto& item : mergeQueue_) { + auto* pbiReader = dynamic_cast(item.reader.get()); + numReads_ += pbiReader->NumReads(); + } + UpdateSort(); + return *this; +} + +template +inline uint32_t PbiFilterCompositeBamReader::NumReads() const +{ + return numReads_; +} + +template +inline void PbiFilterCompositeBamReader::UpdateSort() +{ + std::stable_sort(mergeQueue_.begin(), mergeQueue_.end(), merge_sorter_type{}); +} + +// ------------------------------ +// SequentialCompositeBamReader +// ------------------------------ + +inline SequentialCompositeBamReader::SequentialCompositeBamReader(std::vector bamFiles) +{ + for (auto&& bamFile : bamFiles) + readers_.emplace_back(std::make_unique(std::move(bamFile))); +} + +inline SequentialCompositeBamReader::SequentialCompositeBamReader(const DataSet& dataset) + : SequentialCompositeBamReader{dataset.BamFiles()} +{ +} + +inline bool SequentialCompositeBamReader::GetNext(BamRecord& record) +{ + // try first reader, if successful return true + // else pop reader and try next, until all readers exhausted + while (!readers_.empty()) { + auto& reader = readers_.front(); + if (reader->GetNext(record)) + return true; + else + readers_.pop_front(); + } + + // no readers available + return false; +} + +} // namespace BAM +} // namespace PacBio diff --git a/include/pbbam/internal/DataSetBaseTypes.h b/include/pbbam/internal/DataSetBaseTypes.h new file mode 100644 index 0000000..8d3c13a --- /dev/null +++ b/include/pbbam/internal/DataSetBaseTypes.h @@ -0,0 +1,149 @@ +// Author: Derek Barnett + +#ifndef DATASETBASETYPES_H +#define DATASETBASETYPES_H + +#include "pbbam/Config.h" + +#include "pbbam/internal/DataSetElement.h" + +#include + +namespace PacBio { +namespace BAM { + +class DataSetMetadata; +class Extensions; +class ExternalResources; +class FileIndices; +class Filters; +class Properties; +class Provenance; + +namespace internal { + +class BaseEntityType : public DataSetElement +{ +protected: + BaseEntityType(const std::string& label, const XsdType& xsd = XsdType::BASE_DATA_MODEL); + BaseEntityType(const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd = XsdType::BASE_DATA_MODEL); + +public: + const std::string& CreatedAt() const; + const std::string& Description() const; + const PacBio::BAM::Extensions& Extensions() const; + const std::string& Format() const; + const std::string& ModifiedAt() const; + const std::string& Name() const; + const std::string& ResourceId() const; + const std::string& Tags() const; + const std::string& Version() const; + + std::string& CreatedAt(); + std::string& Description(); + PacBio::BAM::Extensions& Extensions(); + std::string& Format(); + std::string& ModifiedAt(); + std::string& Name(); + std::string& ResourceId(); + std::string& Tags(); + std::string& Version(); + + BaseEntityType& CreatedAt(const std::string& createdAt); + BaseEntityType& Description(const std::string& description); + BaseEntityType& Extensions(const PacBio::BAM::Extensions& extensions); + BaseEntityType& Format(const std::string& format); + BaseEntityType& ModifiedAt(const std::string& modifiedAt); + BaseEntityType& Name(const std::string& name); + BaseEntityType& ResourceId(const std::string& resourceId); + BaseEntityType& Tags(const std::string& tags); + BaseEntityType& Version(const std::string& version); +}; + +class DataEntityType : public BaseEntityType +{ +protected: + DataEntityType(const std::string& label, const XsdType& xsd = XsdType::BASE_DATA_MODEL); + DataEntityType(const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd = XsdType::BASE_DATA_MODEL); + +public: + const std::string& Checksum() const; + const std::string& EncodedValue() const; + const std::string& MetaType() const; + const std::string& SimpleValue() const; + const std::string& TimeStampedName() const; + const std::string& UniqueId() const; + const std::string& ValueDataType() const; + + std::string& Checksum(); + std::string& EncodedValue(); + std::string& MetaType(); + std::string& SimpleValue(); + std::string& TimeStampedName(); + std::string& UniqueId(); + std::string& ValueDataType(); + + DataEntityType& Checksum(const std::string& checksum); + DataEntityType& EncodedValue(const std::string& encodedValue); + DataEntityType& MetaType(const std::string& metatype); + DataEntityType& SimpleValue(const std::string& simpleValue); + DataEntityType& TimeStampedName(const std::string& timeStampedName); + DataEntityType& UniqueId(const std::string& uuid); + DataEntityType& ValueDataType(const std::string& valueDataType); +}; + +class StrictEntityType : public BaseEntityType +{ +protected: + StrictEntityType(const std::string& metatype, const std::string& label, + const XsdType& xsd = XsdType::BASE_DATA_MODEL); + StrictEntityType(const std::string& metatype, const std::string& label, + const FromInputXml& fromInputXml, + const XsdType& xsd = XsdType::BASE_DATA_MODEL); + +public: + const std::string& MetaType() const; + const std::string& TimeStampedName() const; + const std::string& UniqueId() const; + + std::string& MetaType(); + std::string& TimeStampedName(); + std::string& UniqueId(); + + StrictEntityType& MetaType(const std::string& metatype); + StrictEntityType& TimeStampedName(const std::string& timeStampedName); + StrictEntityType& UniqueId(const std::string& uuid); +}; + +class InputOutputDataType : public StrictEntityType +{ +protected: + InputOutputDataType(const std::string& metatype, const std::string& filename, + const std::string& label, const XsdType& xsd = XsdType::BASE_DATA_MODEL); + InputOutputDataType(const std::string& metatype, const std::string& filename, + const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd = XsdType::BASE_DATA_MODEL); +}; + +class IndexedDataType : public InputOutputDataType +{ +protected: + IndexedDataType(const std::string& metatype, const std::string& filename, + const std::string& label, const XsdType& xsd = XsdType::BASE_DATA_MODEL); + IndexedDataType(const std::string& metatype, const std::string& filename, + const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd = XsdType::BASE_DATA_MODEL); + +public: + const PacBio::BAM::FileIndices& FileIndices() const; + PacBio::BAM::FileIndices& FileIndices(); + IndexedDataType& FileIndices(const PacBio::BAM::FileIndices& indices); +}; + +} // namespace internal +} // namespace BAM +} // namespace PacBio + +#endif // DATASETBASETYPES_H diff --git a/include/pbbam/internal/DataSetElement.h b/include/pbbam/internal/DataSetElement.h new file mode 100644 index 0000000..38c7a3f --- /dev/null +++ b/include/pbbam/internal/DataSetElement.h @@ -0,0 +1,202 @@ +// Author: Derek Barnett + +#ifndef DATASETELEMENT_H +#define DATASETELEMENT_H + +#include "pbbam/Config.h" + +#include "pbbam/DataSetXsd.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { +namespace internal { + +class XmlName +{ + // qualified name + // | + // -------------- + // + // ---- --------- + // | | + // prefix local name + +public: + XmlName(std::string fullName, bool verbatim = false); + XmlName(const std::string& localName, const std::string& prefix); + +public: + bool operator==(const XmlName& other) const; + bool operator!=(const XmlName& other) const; + +public: + const boost::string_ref LocalName() const; + const boost::string_ref Prefix() const; + const std::string& QualifiedName() const; + bool Verbatim() const; + +private: + std::string qualifiedName_; + size_t prefixSize_; + size_t localNameOffset_; + size_t localNameSize_; + bool verbatim_; +}; + +struct FromInputXml +{ +}; + +class DataSetElement +{ +public: + DataSetElement(const std::string& label, const XsdType& xsd = XsdType::NONE); + DataSetElement(const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd = XsdType::NONE); + + virtual ~DataSetElement() = default; + +public: + bool operator==(const DataSetElement& other) const; + bool operator!=(const DataSetElement& other) const; + +public: + const std::string& Attribute(const std::string& name) const; + std::string& Attribute(const std::string& name); + const std::map& Attributes() const; + std::map& Attributes(); + bool HasAttribute(const std::string& name) const; + + const std::vector>& Children() const; + std::vector>& Children(); + bool HasChild(const std::string& label) const; + + const boost::string_ref LocalNameLabel() const; + const boost::string_ref PrefixLabel() const; + const std::string& QualifiedNameLabel() const; + bool IsVerbatimLabel() const; + + const std::string& Text() const; + std::string& Text(); + + const XsdType& Xsd() const; + +public: + void Attribute(const std::string& name, const std::string& value); + void Label(const std::string& label); + void Text(const std::string& text); + +public: + size_t NumAttributes() const; + size_t NumChildren() const; + size_t Size() const; + +public: + template + void AddChild(const T& e); + + void AddChild(const DataSetElement& e); + void AddChild(std::shared_ptr e); + void RemoveChild(const DataSetElement& e); + + template + const T& Child(size_t index) const; + + template + T& Child(size_t index); + + template + const T& Child(const std::string& label) const; + + template + T& Child(const std::string& label); + + template + const T& operator[](size_t index) const; + + template + T& operator[](size_t index); + + template + const T& operator[](const std::string& label) const; + + template + T& operator[](const std::string& label); + +protected: + static const std::string& SharedNullString(); + +public: + const std::string& ChildText(const std::string& label) const; + std::string& ChildText(const std::string& label); + void ChildText(const std::string& label, const std::string& text); + +protected: + XsdType xsd_; + XmlName label_; + std::string text_; + std::map attributes_; + std::vector> children_; + +private: + int IndexOf(const std::string& label) const; +}; + +class DataSetElementIteratorBase +{ +public: + bool operator==(const DataSetElementIteratorBase& other) const; + bool operator!=(const DataSetElementIteratorBase& other) const; + +protected: + DataSetElementIteratorBase(const DataSetElement* parent, size_t i); + void Advance(); + +protected: + const DataSetElement* parent_; + size_t index_; +}; + +template +class DataSetElementIterator : public DataSetElementIteratorBase +{ +public: + DataSetElementIterator(const DataSetElement* parent, size_t i); + + T& operator*(); + T* operator->(); + + DataSetElementIterator& operator++(); + DataSetElementIterator operator++(int); +}; + +template +class DataSetElementConstIterator : public DataSetElementIteratorBase +{ +public: + DataSetElementConstIterator(const DataSetElement* parent, size_t i); + + const T& operator*() const; + const T* operator->() const; + + DataSetElementConstIterator& operator++(); + DataSetElementConstIterator operator++(int); +}; + +} // namespace internal +} // namespace BAM +} // namespace PacBio + +#include "pbbam/internal/DataSetElement.inl" + +#endif // DATASETELEMENT_H diff --git a/include/pbbam/internal/DataSetElement.inl b/include/pbbam/internal/DataSetElement.inl new file mode 100644 index 0000000..7e5f261 --- /dev/null +++ b/include/pbbam/internal/DataSetElement.inl @@ -0,0 +1,411 @@ +// Author: Derek Barnett + +#include "pbbam/internal/DataSetElement.h" + +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { +namespace internal { + +// ---------------- +// DataSetElement +// ---------------- + +inline DataSetElement::DataSetElement(const std::string& label, const XsdType& xsd) + : xsd_(xsd), label_(label) +{ +} + +inline DataSetElement::DataSetElement(const std::string& label, const FromInputXml&, + const XsdType& xsd) + : xsd_(xsd), label_(label, true) +{ +} + +inline bool DataSetElement::operator==(const DataSetElement& other) const +{ + return std::tie(xsd_, label_, text_, attributes_, children_) == + std::tie(other.xsd_, other.label_, other.text_, other.attributes_, other.children_); +} + +inline bool DataSetElement::operator!=(const DataSetElement& other) const +{ + return !(*this == other); +} + +template +const T& DataSetElement::operator[](size_t index) const +{ + return Child(index); +} + +template +T& DataSetElement::operator[](size_t index) +{ + return Child(index); +} + +template +const T& DataSetElement::operator[](const std::string& label) const +{ + return Child(label); +} + +template +T& DataSetElement::operator[](const std::string& label) +{ + return Child(label); +} + +template +inline void DataSetElement::AddChild(const T& e) +{ + children_.push_back(std::make_shared(e)); +} + +inline void DataSetElement::AddChild(const DataSetElement& e) +{ + children_.push_back(std::make_shared(e)); +} + +inline void DataSetElement::AddChild(std::shared_ptr e) { children_.push_back(e); } + +inline std::string& DataSetElement::Attribute(const std::string& name) { return attributes_[name]; } + +inline const std::string& DataSetElement::Attribute(const std::string& name) const +{ + auto iter = attributes_.find(name); + if (iter == attributes_.cend()) return SharedNullString(); + return iter->second; +} + +inline void DataSetElement::Attribute(const std::string& name, const std::string& value) +{ + attributes_[name] = value; +} + +inline const std::map& DataSetElement::Attributes() const +{ + return attributes_; +} + +inline std::map& DataSetElement::Attributes() { return attributes_; } + +template +inline const T& DataSetElement::Child(size_t index) const +{ + DataSetElement* child = children_.at(index).get(); + if (child == nullptr) + throw std::runtime_error{"DataSetElement: cannot access null child at index: " + + std::to_string(index)}; + const T* c = dynamic_cast(child); + return *c; +} + +template +inline T& DataSetElement::Child(size_t index) +{ + DataSetElement* child = children_.at(index).get(); + if (child == nullptr) + throw std::runtime_error{"DataSetElement: cannot access null child at index: " + + std::to_string(index)}; + T* c = dynamic_cast(child); + return *c; +} + +template +inline const T& DataSetElement::Child(const std::string& label) const +{ + const auto index = IndexOf(label); + return Child(index); +} + +template +inline T& DataSetElement::Child(const std::string& label) +{ + const int i = IndexOf(label); + if (i >= 0) { + assert(static_cast(i) < NumChildren()); + return Child(i); + } else { + AddChild(T()); + return Child(NumChildren() - 1); + } +} + +template <> +inline DataSetElement& DataSetElement::Child(const std::string& label) +{ + const int i = IndexOf(label); + if (i >= 0) { + assert(static_cast(i) < NumChildren()); + return Child(i); + } else { + AddChild(DataSetElement{label}); + return Child(NumChildren() - 1); + } +} + +inline const std::vector>& DataSetElement::Children() const +{ + return children_; +} + +inline std::vector>& DataSetElement::Children() +{ + return children_; +} + +inline const std::string& DataSetElement::ChildText(const std::string& label) const +{ + if (!HasChild(label)) return SharedNullString(); + return Child(label).Text(); +} + +inline std::string& DataSetElement::ChildText(const std::string& label) +{ + if (!HasChild(label)) AddChild(DataSetElement(label)); + return Child(label).Text(); +} + +inline bool DataSetElement::HasAttribute(const std::string& name) const +{ + return attributes_.find(name) != attributes_.cend(); +} + +inline bool DataSetElement::HasChild(const std::string& label) const +{ + return IndexOf(label) != -1; +} + +inline int DataSetElement::IndexOf(const std::string& label) const +{ + const size_t count = NumChildren(); + for (size_t i = 0; i < count; ++i) { + const DataSetElement& child = *(children_.at(i).get()); + if (child.LocalNameLabel() == label || child.QualifiedNameLabel() == label || + child.label_ == label) + return i; + } + return -1; +} + +inline const boost::string_ref DataSetElement::LocalNameLabel() const { return label_.LocalName(); } + +inline const boost::string_ref DataSetElement::PrefixLabel() const { return label_.Prefix(); } + +inline const std::string& DataSetElement::QualifiedNameLabel() const +{ + return label_.QualifiedName(); +} + +inline void DataSetElement::Label(const std::string& label) { label_ = XmlName(label, true); } + +inline size_t DataSetElement::NumAttributes() const { return attributes_.size(); } + +inline size_t DataSetElement::NumChildren() const { return children_.size(); } + +inline size_t DataSetElement::Size() const { return children_.size(); } + +inline void DataSetElement::RemoveChild(const DataSetElement& e) +{ + std::vector> newChildren; + for (std::shared_ptr& child : children_) { + if (*(child.get()) != e) newChildren.push_back(std::move(child)); + } + children_ = std::move(newChildren); +} + +inline void DataSetElement::ChildText(const std::string& label, const std::string& text) +{ + if (!HasChild(label)) { + DataSetElement e(label); + e.Text(text); + AddChild(e); + } else { + Child(label).Text(text); + } +} + +inline bool DataSetElement::IsVerbatimLabel() const { return label_.Verbatim(); } + +inline const std::string& DataSetElement::Text() const { return text_; } + +inline std::string& DataSetElement::Text() { return text_; } + +inline void DataSetElement::Text(const std::string& text) { text_ = text; } + +inline const XsdType& DataSetElement::Xsd() const { return xsd_; } + +// ---------------------------- +// DataSetElementIteratorBase +// ---------------------------- + +inline DataSetElementIteratorBase::DataSetElementIteratorBase(const DataSetElement* parent, + size_t i) + : parent_(parent), index_(i) +{ +} + +inline bool DataSetElementIteratorBase::operator==(const DataSetElementIteratorBase& other) const +{ + return std::tie(parent_, index_) == std::tie(other.parent_, other.index_); +} + +inline bool DataSetElementIteratorBase::operator!=(const DataSetElementIteratorBase& other) const +{ + return !(*this == other); +} + +inline void DataSetElementIteratorBase::Advance() +{ + if (index_ >= parent_->NumChildren()) { + parent_ = nullptr; + return; + } + ++index_; +} + +// ------------------------ +// DataSetElementIterator +// ------------------------ + +template +inline DataSetElementIterator::DataSetElementIterator(const DataSetElement* parent, size_t i) + : DataSetElementIteratorBase(parent, i) +{ +} + +template +inline T& DataSetElementIterator::operator*() +{ + return parent_->template Child(index_); +} + +template +inline T* DataSetElementIterator::operator->() +{ + return &(operator*()); +} + +template +inline DataSetElementIterator& DataSetElementIterator::operator++() +{ + Advance(); + return *this; +} + +template +inline DataSetElementIterator DataSetElementIterator::operator++(int) +{ + DataSetElementIterator result(*this); + ++(*this); + return result; +} + +// ----------------------------- +// DataSetElementConstIterator +// ----------------------------- + +template +inline DataSetElementConstIterator::DataSetElementConstIterator(const DataSetElement* parent, + size_t i) + : DataSetElementIteratorBase(parent, i) +{ +} + +template +inline const T& DataSetElementConstIterator::operator*() const +{ + return parent_->template Child(index_); +} + +template +inline const T* DataSetElementConstIterator::operator->() const +{ + return &(operator*()); +} + +template +inline DataSetElementConstIterator& DataSetElementConstIterator::operator++() +{ + Advance(); + return *this; +} + +template +DataSetElementConstIterator DataSetElementConstIterator::operator++(int) +{ + DataSetElementConstIterator result(*this); + ++(*this); + return result; +} + +// ---------------- +// XmlName +// ---------------- + +inline XmlName::XmlName(std::string fullName, bool verbatim) + : qualifiedName_(std::move(fullName)) + , prefixSize_(0) + , localNameOffset_(0) + , localNameSize_(0) + , verbatim_(verbatim) +{ + const size_t colonFound = qualifiedName_.find(':'); + if (colonFound == std::string::npos || colonFound == 0) + localNameSize_ = qualifiedName_.size(); + else { + prefixSize_ = colonFound; + localNameSize_ = (qualifiedName_.size() - colonFound) - 1; + } + + // adjust for colon if prefix present + localNameOffset_ = prefixSize_; + if (prefixSize_ != 0) ++localNameOffset_; +} + +inline XmlName::XmlName(const std::string& localName, const std::string& prefix) + : prefixSize_(prefix.size()) + , localNameOffset_(prefixSize_) + , localNameSize_(localName.size()) + , verbatim_(true) +{ + qualifiedName_.clear(); + qualifiedName_.reserve(localNameSize_ + prefixSize_ + 1); + qualifiedName_.append(prefix); + if (!qualifiedName_.empty()) qualifiedName_.append(1, ':'); + qualifiedName_.append(localName); + + // adjust for colon if prefix present + if (prefixSize_ != 0) ++localNameOffset_; +} + +inline bool XmlName::operator==(const XmlName& other) const +{ + return qualifiedName_ == other.qualifiedName_; +} + +inline bool XmlName::operator!=(const XmlName& other) const { return !(*this == other); } + +inline const boost::string_ref XmlName::LocalName() const +{ + return boost::string_ref(qualifiedName_.data() + localNameOffset_, localNameSize_); +} + +inline const boost::string_ref XmlName::Prefix() const +{ + return boost::string_ref(qualifiedName_.data(), prefixSize_); +} + +inline const std::string& XmlName::QualifiedName() const { return qualifiedName_; } + +inline bool XmlName::Verbatim() const { return verbatim_; } + +} // namespace internal +} // namespace BAM +} // namespace PacBio diff --git a/include/pbbam/internal/PbiBasicTypes.inl b/include/pbbam/internal/PbiBasicTypes.inl new file mode 100644 index 0000000..168813e --- /dev/null +++ b/include/pbbam/internal/PbiBasicTypes.inl @@ -0,0 +1,28 @@ +// File Description +/// \file PbiBasicTypes.inl +/// \brief Inline implementations for the basic data structures used in PBI lookups. +// +// Author: Derek Barnett + +#include "pbbam/PbiBasicTypes.h" + +#include + +namespace PacBio { +namespace BAM { + +inline IndexResultBlock::IndexResultBlock(size_t idx, size_t numReads) + : firstIndex_{idx} + , numReads_{numReads} +{ } + +inline bool IndexResultBlock::operator==(const IndexResultBlock& other) const +{ + return std::tie(firstIndex_, numReads_, virtualOffset_) == std::tie(other.firstIndex_, other.numReads_, other.virtualOffset_); +} + +inline bool IndexResultBlock::operator!=(const IndexResultBlock& other) const +{ return !(*this == other); } + +} // namespace BAM +} // namespace PacBio diff --git a/include/pbbam/internal/PbiFilter.inl b/include/pbbam/internal/PbiFilter.inl new file mode 100644 index 0000000..276c445 --- /dev/null +++ b/include/pbbam/internal/PbiFilter.inl @@ -0,0 +1,227 @@ +// File Description +/// \file PbiFilter.inl +/// \brief Inline implementations for the PbiFilter class. +// +// Author: Derek Barnett + +#include "pbbam/PbiFilter.h" + +#include +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { +namespace internal { + +/// \internal +/// +/// This class wraps a the basic PBI filter (whether property filter or some operator +/// e.g. union, intersect, etc.). The wrapper allows PbiFilters to hold heterogeneous, +/// recursive filter types - without exposing pointers & worrying about memory ownership +/// issues between client & library. +/// +/// Filters can be given by value from client code and we will wrap them for composition. +/// +/// \code{.cpp} +/// PbiFilter f1(PbiZmwFilter(42)); +/// PbiFilter f2; +/// f2.Add(PbiQueryLengthFilter(3000, GREATER_THAN_EQUAL)); +/// f2.Add(MyApplicationCustomFilter("foo")); +/// PbiFilter intersect = PbiFilter::Intersect(f1, f2); +/// ... +/// \endcode +/// +struct FilterWrapper +{ +public: + template + FilterWrapper(T x); + + FilterWrapper(const FilterWrapper& other); + FilterWrapper(FilterWrapper&&) noexcept = default; + FilterWrapper& operator=(const FilterWrapper& other); + FilterWrapper& operator=(FilterWrapper&&) noexcept = default; + +public: + bool Accepts(const PacBio::BAM::PbiRawData& idx, const size_t row) const; + +private: + struct WrapperInterface + { + virtual ~WrapperInterface() = default; + virtual WrapperInterface* Clone() const = 0; + virtual bool Accepts(const PacBio::BAM::PbiRawData& idx, const size_t row) const = 0; + }; + + template + struct WrapperImpl : public WrapperInterface + { + WrapperImpl(T x); + WrapperImpl(const WrapperImpl& other); + WrapperInterface* Clone() const override; + bool Accepts(const PacBio::BAM::PbiRawData& idx, const size_t row) const override; + T data_; + }; + +private: + std::unique_ptr self_; +}; + +// --------------- +// FilterWrapper +// --------------- + +template +inline FilterWrapper::FilterWrapper(T x) : self_{std::make_unique>(std::move(x))} +{} + +inline FilterWrapper::FilterWrapper(const FilterWrapper& other) : self_{other.self_->Clone()} {} + +inline FilterWrapper& FilterWrapper::operator=(const FilterWrapper& other) +{ + self_.reset(other.self_->Clone()); + return *this; +} + +inline bool FilterWrapper::Accepts(const PbiRawData& idx, const size_t row) const +{ + return self_->Accepts(idx, row); +} + +// ---------------- +// WrapperImpl +// ---------------- + +template +inline FilterWrapper::WrapperImpl::WrapperImpl(T x) + : FilterWrapper::WrapperInterface{}, data_(std::move(x)) +{ + BOOST_CONCEPT_ASSERT((PbiFilterConcept)); +} + +template +inline FilterWrapper::WrapperImpl::WrapperImpl(const WrapperImpl& other) + : FilterWrapper::WrapperInterface{}, data_(other.data_) +{} + +template +inline FilterWrapper::WrapperInterface* FilterWrapper::WrapperImpl::Clone() const +{ + return new WrapperImpl(*this); +} + +template +inline bool FilterWrapper::WrapperImpl::Accepts(const PbiRawData& idx, const size_t row) const +{ + return data_.Accepts(idx, row); +} + +struct PbiFilterPrivate +{ + PbiFilterPrivate(PbiFilter::CompositionType type = PbiFilter::INTERSECT) : type_{type} {} + + template + void Add(T filter) + { + filters_.emplace_back(std::move(filter)); + } + + std::unique_ptr DeepCopy() + { + auto copy = std::make_unique(type_); + copy->filters_ = this->filters_; + return copy; + } + + bool Accepts(const PbiRawData& idx, const size_t row) const + { + // no filter -> accepts every record + if (filters_.empty()) return true; + + // intersection of child filters + if (type_ == PbiFilter::INTERSECT) { + for (const auto& filter : filters_) { + if (!filter.Accepts(idx, row)) return false; // break early on failure + } + return true; // all passed + } + + // union of child filters + else if (type_ == PbiFilter::UNION) { + for (const auto& filter : filters_) { + if (filter.Accepts(idx, row)) return true; // break early on pass + } + return false; // none passed + } + + else + //assert(false); // invalid composite filter type + throw std::runtime_error{"PbiFilter: invalid composite filter type"}; + } + + PbiFilter::CompositionType type_; + std::vector filters_; +}; + +} // namespace internal + +inline PbiFilter::PbiFilter(const CompositionType type) + : d_{std::make_unique(type)} +{} + +template +inline PbiFilter::PbiFilter(T filter) : d_{std::make_unique()} +{ + Add(std::move(filter)); +} + +inline PbiFilter::PbiFilter(std::vector filters) + : d_{std::make_unique()} +{ + Add(std::move(filters)); +} + +inline PbiFilter::PbiFilter(const PbiFilter& other) : d_{other.d_->DeepCopy()} {} + +inline PbiFilter& PbiFilter::operator=(const PbiFilter& other) +{ + d_ = other.d_->DeepCopy(); + return *this; +} + +inline bool PbiFilter::Accepts(const PacBio::BAM::PbiRawData& idx, const size_t row) const +{ + return d_->Accepts(idx, row); +} + +template +inline PbiFilter& PbiFilter::Add(T filter) +{ + d_->Add(std::move(filter)); + return *this; +} + +inline PbiFilter& PbiFilter::Add(PbiFilter filter) +{ + d_->Add(std::move(filter)); + return *this; +} + +inline PbiFilter& PbiFilter::Add(std::vector filters) +{ + for (auto&& filter : filters) + d_->Add(std::move(filter)); + return *this; +} + +inline bool PbiFilter::IsEmpty() const { return d_->filters_.empty(); } + +inline size_t PbiFilter::NumChildren() const { return d_->filters_.size(); } + +inline PbiFilter::CompositionType PbiFilter::Type() const { return d_->type_; } + +} // namespace BAM +} // namespace PacBio diff --git a/include/pbbam/internal/PbiFilterTypes.inl b/include/pbbam/internal/PbiFilterTypes.inl new file mode 100644 index 0000000..7e043a4 --- /dev/null +++ b/include/pbbam/internal/PbiFilterTypes.inl @@ -0,0 +1,508 @@ +// File Description +/// \file PbiFilterTypes.inl +/// \brief Inline implementations for the built-in PBI filters. +// +// Author: Derek Barnett + +#include "pbbam/PbiFilterTypes.h" + +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +namespace internal { + +template +inline FilterBase::FilterBase(T value, const Compare::Type cmp) + : value_{std::move(value)}, cmp_{cmp} +{} + +template +inline FilterBase::FilterBase(std::vector values, const Compare::Type cmp) + : multiValue_{std::move(values)}, cmp_{cmp} +{ + // "=="/"!=" can come in from XML, e.g. " + // switch to whitelist/blacklist containment for multi-value filters + if (cmp_ == Compare::EQUAL) + cmp_ = Compare::CONTAINS; + else if (cmp_ == Compare::NOT_EQUAL) + cmp_ = Compare::NOT_CONTAINS; + + if (cmp_ != Compare::CONTAINS && cmp_ != Compare::NOT_CONTAINS) { + throw std::runtime_error{ + "PbiFilter: multi-valued filters (e.g. whitelists) can only check containment."}; + } +} + +template +inline bool FilterBase::CompareHelper(const T& lhs) const +{ + if (multiValue_ == boost::none) + return CompareSingleHelper(lhs); + else + return CompareMultiHelper(lhs); +} + +template +inline bool FilterBase::CompareMultiHelper(const T& lhs) const +{ + // multi-value filters are whitelist/blacklist + assert(cmp_ == Compare::CONTAINS || cmp_ == Compare::NOT_CONTAINS); + + // whitelist - return true on any hit + if (cmp_ == Compare::CONTAINS) { + for (const auto x : multiValue_.get()) + if (x == lhs) return true; + return false; + } + // blacklist - return false on any hit + else { + for (const auto x : multiValue_.get()) + if (x == lhs) return false; + return true; + } +} + +template +inline bool FilterBase::CompareSingleHelper(const T& lhs) const +{ + return Compare::Check(lhs, value_, cmp_); +} + +template <> +inline bool FilterBase::CompareSingleHelper(const LocalContextFlags& lhs) const +{ + switch (cmp_) { + case Compare::EQUAL: + return lhs == value_; + case Compare::LESS_THAN: + return lhs < value_; + case Compare::LESS_THAN_EQUAL: + return lhs <= value_; + case Compare::GREATER_THAN: + return lhs > value_; + case Compare::GREATER_THAN_EQUAL: + return lhs >= value_; + case Compare::NOT_EQUAL: + return lhs != value_; + case Compare::CONTAINS: + return ((lhs & value_) != 0); + case Compare::NOT_CONTAINS: + return ((lhs & value_) == 0); + + default: + assert(false); + throw std::runtime_error{"PbiFilter: unknown compare type (" + + Compare::TypeToName(cmp_) + ")"}; + } +} + +// BarcodeDataFilterBase + +template +inline BarcodeDataFilterBase::BarcodeDataFilterBase(T value, const Compare::Type cmp) + : FilterBase{std::move(value), cmp} +{} + +template +inline BarcodeDataFilterBase::BarcodeDataFilterBase(std::vector values, + const Compare::Type cmp) + : FilterBase{std::move(values), cmp} +{} + +template +inline bool BarcodeDataFilterBase::BarcodeDataFilterBase::Accepts(const PbiRawData& idx, + const size_t row) const +{ + const PbiRawBarcodeData& barcodeData = idx.BarcodeData(); + switch (field) { + case PbiFile::BarcodeField::BC_FORWARD: + return FilterBase::CompareHelper(barcodeData.bcForward_.at(row)); + case PbiFile::BarcodeField::BC_REVERSE: + return FilterBase::CompareHelper(barcodeData.bcReverse_.at(row)); + case PbiFile::BarcodeField::BC_QUALITY: + return FilterBase::CompareHelper(barcodeData.bcQual_.at(row)); + default: + assert(false); + throw std::runtime_error{"PbiFilter: unknown barcode field requested."}; + } +} + +// BasicDataFilterBase + +template +inline BasicDataFilterBase::BasicDataFilterBase(T value, const Compare::Type cmp) + : FilterBase{std::move(value), cmp} +{} + +template +inline BasicDataFilterBase::BasicDataFilterBase(std::vector values, + const Compare::Type cmp) + : FilterBase{std::move(values), cmp} +{} + +template +inline bool BasicDataFilterBase::BasicDataFilterBase::Accepts(const PbiRawData& idx, + const size_t row) const +{ + const PbiRawBasicData& basicData = idx.BasicData(); + switch (field) { + case PbiFile::BasicField::RG_ID: + return FilterBase::CompareHelper(basicData.rgId_.at(row)); + case PbiFile::BasicField::Q_START: + return FilterBase::CompareHelper(basicData.qStart_.at(row)); + case PbiFile::BasicField::Q_END: + return FilterBase::CompareHelper(basicData.qEnd_.at(row)); + case PbiFile::BasicField::ZMW: + return FilterBase::CompareHelper(basicData.holeNumber_.at(row)); + case PbiFile::BasicField::READ_QUALITY: + return FilterBase::CompareHelper(basicData.readQual_.at(row)); + // NOTE(DB): PbiFile::BasicField::CONTEXT_FLAG has its own specialization + default: + assert(false); + throw std::runtime_error{"PbiFilter: unknown basic data field requested."}; + } +} + +// this typedef exists purely so that the next method signature isn't 2 screen widths long +using LocalContextFilter__ = + BasicDataFilterBase; + +template <> +inline bool LocalContextFilter__::BasicDataFilterBase::Accepts(const PbiRawData& idx, + const size_t row) const +{ + const auto& basicData = idx.BasicData(); + const auto rowFlags = static_cast(basicData.ctxtFlag_.at(row)); + return FilterBase::CompareHelper(rowFlags); +} + +// BasicDataFilterBase + +template +inline MappedDataFilterBase::MappedDataFilterBase(T value, const Compare::Type cmp) + : FilterBase{std::move(value), cmp} +{} + +template +inline MappedDataFilterBase::MappedDataFilterBase(std::vector values, + const Compare::Type cmp) + : FilterBase{std::move(values), cmp} +{} + +template <> +inline bool +MappedDataFilterBase::MappedDataFilterBase::Accepts( + const PbiRawData& idx, const size_t row) const +{ + const PbiRawMappedData& mappedData = idx.MappedData(); + const Strand strand = (mappedData.revStrand_.at(row) == 1 ? Strand::REVERSE : Strand::FORWARD); + return FilterBase::CompareHelper(strand); +} + +template +inline bool MappedDataFilterBase::MappedDataFilterBase::Accepts(const PbiRawData& idx, + const size_t row) const +{ + const PbiRawMappedData& mappedData = idx.MappedData(); + switch (field) { + case PbiFile::MappedField::T_ID: + return FilterBase::CompareHelper(mappedData.tId_.at(row)); + case PbiFile::MappedField::T_START: + return FilterBase::CompareHelper(mappedData.tStart_.at(row)); + case PbiFile::MappedField::T_END: + return FilterBase::CompareHelper(mappedData.tEnd_.at(row)); + case PbiFile::MappedField::A_START: + return FilterBase::CompareHelper(mappedData.aStart_.at(row)); + case PbiFile::MappedField::A_END: + return FilterBase::CompareHelper(mappedData.aEnd_.at(row)); + case PbiFile::MappedField::N_M: + return FilterBase::CompareHelper(mappedData.nM_.at(row)); + case PbiFile::MappedField::N_MM: + return FilterBase::CompareHelper(mappedData.nMM_.at(row)); + case PbiFile::MappedField::N_DEL: + return FilterBase::CompareHelper(mappedData.NumDeletedBasesAt(row)); + case PbiFile::MappedField::N_INS: + return FilterBase::CompareHelper(mappedData.NumInsertedBasesAt(row)); + case PbiFile::MappedField::MAP_QUALITY: + return FilterBase::CompareHelper(mappedData.mapQV_.at(row)); + default: + assert(false); + throw std::runtime_error{"PbiFilter: unknown mapped data field requested."}; + } +} + +} // namespace internal + +// PbiAlignedEndFilter + +inline PbiAlignedEndFilter::PbiAlignedEndFilter(const uint32_t position, const Compare::Type cmp) + : internal::MappedDataFilterBase{position, cmp} +{} + +// PbiAlignedLengthFilter + +inline PbiAlignedLengthFilter::PbiAlignedLengthFilter(const uint32_t length, + const Compare::Type cmp) + : internal::FilterBase{length, cmp} +{} + +// PbiAlignedStartFilter + +inline PbiAlignedStartFilter::PbiAlignedStartFilter(const uint32_t position, + const Compare::Type cmp) + : internal::MappedDataFilterBase{position, cmp} +{} + +// PbiAlignedStrandFilter + +inline PbiAlignedStrandFilter::PbiAlignedStrandFilter(const Strand strand, const Compare::Type cmp) + : internal::MappedDataFilterBase{strand, cmp} +{ + if (cmp != Compare::EQUAL && cmp != Compare::NOT_EQUAL) + throw std::runtime_error{ + "PbiFilter: compare type for aligned strand must be either EQUAL or NOT_EQUAL"}; +} + +// PbiBarcodeFilter + +inline PbiBarcodeFilter::PbiBarcodeFilter(const int16_t barcode, const Compare::Type cmp) + : compositeFilter_{PbiFilter::Union( + {PbiBarcodeForwardFilter{barcode, cmp}, PbiBarcodeReverseFilter{barcode, cmp}})} +{} + +inline PbiBarcodeFilter::PbiBarcodeFilter(std::vector barcodes, const Compare::Type cmp) + : compositeFilter_{PbiFilter::Union( + {PbiBarcodeForwardFilter{barcodes, cmp}, PbiBarcodeReverseFilter{barcodes, cmp}})} +{} + +inline bool PbiBarcodeFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + return compositeFilter_.Accepts(idx, row); +} + +// PbiBarcodeForwardFilter + +inline PbiBarcodeForwardFilter::PbiBarcodeForwardFilter(const int16_t bcFwdId, + const Compare::Type cmp) + : internal::BarcodeDataFilterBase{bcFwdId, cmp} +{} + +inline PbiBarcodeForwardFilter::PbiBarcodeForwardFilter(std::vector barcodes, + const Compare::Type cmp) + : internal::BarcodeDataFilterBase{ + std::move(barcodes), cmp} +{} + +// PbiBarcodeQualityFilter + +inline PbiBarcodeQualityFilter::PbiBarcodeQualityFilter(const uint8_t bcQuality, + const Compare::Type cmp) + : internal::BarcodeDataFilterBase{bcQuality, cmp} +{} + +// PbiBarcodeReverseFilter + +inline PbiBarcodeReverseFilter::PbiBarcodeReverseFilter(const int16_t bcRevId, + const Compare::Type cmp) + : internal::BarcodeDataFilterBase{bcRevId, cmp} +{} + +inline PbiBarcodeReverseFilter::PbiBarcodeReverseFilter(std::vector barcodes, + const Compare::Type cmp) + : internal::BarcodeDataFilterBase{ + std::move(barcodes), cmp} +{} + +// PbiBarcodesFilter + +inline PbiBarcodesFilter::PbiBarcodesFilter(const std::pair barcodes, + const Compare::Type cmp) + : PbiBarcodesFilter{barcodes.first, barcodes.second, cmp} +{} + +inline PbiBarcodesFilter::PbiBarcodesFilter(const int16_t bcForward, const int16_t bcReverse, + const Compare::Type cmp) + : compositeFilter_{PbiFilter::Intersection( + {PbiBarcodeForwardFilter{bcForward, cmp}, PbiBarcodeReverseFilter{bcReverse, cmp}})} +{} + +inline bool PbiBarcodesFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + return compositeFilter_.Accepts(idx, row); +} + +// PbiIdentityFilter + +inline PbiIdentityFilter::PbiIdentityFilter(const float identity, const Compare::Type cmp) + : internal::FilterBase{identity, cmp} +{} + +// PbiLocalContextFilter + +inline PbiLocalContextFilter::PbiLocalContextFilter(const LocalContextFlags& flags, + const Compare::Type cmp) + : internal::BasicDataFilterBase{flags, + cmp} +{} + +// PbiMapQualityFilter + +inline PbiMapQualityFilter::PbiMapQualityFilter(const uint8_t mapQual, const Compare::Type cmp) + : internal::MappedDataFilterBase{mapQual, cmp} +{} + +// PbiMovieNameFilter + +inline bool PbiMovieNameFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + const bool found = compositeFilter_.Accepts(idx, row); + if (cmp_ == Compare::EQUAL || cmp_ == Compare::CONTAINS) + return found; + else if (cmp_ == Compare::NOT_EQUAL || cmp_ == Compare::NOT_CONTAINS) + return !found; + else + throw std::runtime_error{"unsupported compare type on movie name filter"}; +} + +// PbiNumDeletedBasesFilter + +inline PbiNumDeletedBasesFilter::PbiNumDeletedBasesFilter(const size_t numDeletions, + const Compare::Type cmp) + : internal::MappedDataFilterBase{numDeletions, cmp} +{} + +// PbiNumInsertedBasesFilter + +inline PbiNumInsertedBasesFilter::PbiNumInsertedBasesFilter(const size_t numInsertions, + const Compare::Type cmp) + : internal::MappedDataFilterBase{numInsertions, cmp} +{} + +// PbiNumMatchesFilter + +inline PbiNumMatchesFilter::PbiNumMatchesFilter(const size_t numMatchedBases, + const Compare::Type cmp) + : internal::MappedDataFilterBase{numMatchedBases, cmp} +{} + +// PbiNumMismatchesFilter + +inline PbiNumMismatchesFilter::PbiNumMismatchesFilter(const size_t numMismatchedBases, + const Compare::Type cmp) + : internal::MappedDataFilterBase{numMismatchedBases, cmp} +{} + +// PbiQueryEndFilter + +inline PbiQueryEndFilter::PbiQueryEndFilter(const int32_t position, const Compare::Type cmp) + : internal::BasicDataFilterBase{position, cmp} +{} + +// PbiQueryLengthFilter + +inline PbiQueryLengthFilter::PbiQueryLengthFilter(const int32_t length, const Compare::Type cmp) + : internal::FilterBase{length, cmp} +{} + +// PbiQueryStartFilter + +inline PbiQueryStartFilter::PbiQueryStartFilter(const int32_t position, const Compare::Type cmp) + : internal::BasicDataFilterBase{position, cmp} +{} + +// PbiReadAccuracyFilter + +inline PbiReadAccuracyFilter::PbiReadAccuracyFilter(const Accuracy accuracy, + const Compare::Type cmp) + : internal::BasicDataFilterBase{accuracy, cmp} +{} + +// PbiReferenceEndFilter + +inline PbiReferenceEndFilter::PbiReferenceEndFilter(const uint32_t tEnd, const Compare::Type cmp) + : internal::MappedDataFilterBase{tEnd, cmp} +{} + +// PbiReferenceIdFilter + +inline PbiReferenceIdFilter::PbiReferenceIdFilter(const int32_t tId, const Compare::Type cmp) + : internal::MappedDataFilterBase{tId, cmp} +{} + +inline PbiReferenceIdFilter::PbiReferenceIdFilter(std::vector tIds, + const Compare::Type cmp) + : internal::MappedDataFilterBase{std::move(tIds), cmp} +{} + +// PbiReferenceStartFilter + +inline PbiReferenceStartFilter::PbiReferenceStartFilter(const uint32_t tStart, + const Compare::Type cmp) + : internal::MappedDataFilterBase{tStart, cmp} +{} + +// PbiZmwFilter + +inline PbiZmwFilter::PbiZmwFilter(const int32_t zmw, const Compare::Type cmp) + : internal::BasicDataFilterBase{zmw, cmp} +{} + +inline PbiZmwFilter::PbiZmwFilter(std::vector whitelist, const Compare::Type cmp) + : internal::BasicDataFilterBase{std::move(whitelist), cmp} +{} + +// PbiZmwModuloFilter + +inline PbiZmwModuloFilter::PbiZmwModuloFilter(const uint32_t denominator, const uint32_t value, + const FilterHash hashType, const Compare::Type cmp) + : denominator_{denominator}, value_{value}, hash_{hashType}, cmp_{cmp} +{} + +inline uint32_t UnsignedLongIntCast(const int32_t zm) { return static_cast(zm); } + +inline uint32_t BoostHashCombine(const int32_t zm) +{ + constexpr static const uint16_t mask = 0xFFFF; + + const uint16_t upper = (zm >> 16) & mask; + const uint16_t lower = zm & mask; + + // FIXME: discrepancies with Python API. Will return to nail down. + + size_t seed = 0; + boost::hash_combine(seed, upper); + boost::hash_combine(seed, lower); + return static_cast(seed); +} + +inline bool PbiZmwModuloFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + const auto zm = idx.BasicData().holeNumber_.at(row); + + uint32_t hashValue; + switch (hash_) { + case FilterHash::UNSIGNED_LONG_CAST: { + hashValue = UnsignedLongIntCast(zm); + break; + } + + case FilterHash::BOOST_HASH_COMBINE: { + hashValue = BoostHashCombine(zm); + break; + } + + default: + throw std::runtime_error{"unsupported filter hash type"}; + } + + const auto modResult = hashValue % denominator_; + return Compare::Check(modResult, value_, cmp_); +} + +} // namespace BAM +} // namespace PacBio diff --git a/include/pbbam/internal/QueryBase.h b/include/pbbam/internal/QueryBase.h new file mode 100644 index 0000000..427c49a --- /dev/null +++ b/include/pbbam/internal/QueryBase.h @@ -0,0 +1,107 @@ +// Author: Derek Barnett + +#ifndef QUERYBASE_H +#define QUERYBASE_H + +#include "pbbam/Config.h" + +#include "pbbam/BamFile.h" +#include "pbbam/BamRecord.h" +#include "pbbam/DataSet.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { +namespace internal { + +template +class QueryBase; + +template +class QueryIteratorBase +{ +public: + ~QueryIteratorBase() = default; + + bool operator==(const QueryIteratorBase& other) const; + bool operator!=(const QueryIteratorBase& other) const; + +protected: + QueryIteratorBase() = default; + QueryIteratorBase(QueryBase& query); + + void ReadNext(); + +protected: + QueryBase* query_ = nullptr; + T record_; +}; + +template +class QueryIterator : public QueryIteratorBase +{ +public: + QueryIterator() = default; + QueryIterator(QueryBase& query); + + T& operator*(); + T* operator->(); + + QueryIterator& operator++(); + QueryIterator operator++(int); +}; + +template +class QueryConstIterator : public QueryIteratorBase +{ +public: + QueryConstIterator() = default; + QueryConstIterator(const QueryBase& query); + + const T& operator*() const; + const T* operator->() const; + + QueryConstIterator& operator++(); + QueryConstIterator operator++(int); +}; + +template +class QueryBase +{ + +public: + using iterator = QueryIterator; + using const_iterator = QueryConstIterator; + +public: + virtual ~QueryBase() = default; + +public: + QueryConstIterator begin() const; + QueryConstIterator cbegin() const; + QueryIterator begin(); + + QueryConstIterator end() const; + QueryConstIterator cend() const; + QueryIterator end(); + +public: + virtual bool GetNext(T& r) = 0; + +protected: + QueryBase() = default; +}; + +using IQuery = QueryBase; +using IGroupQuery = QueryBase>; + +} // namespace internal +} // namespace BAM +} // namespace PacBio + +#include "pbbam/internal/QueryBase.inl" + +#endif // QUERYBASE_H diff --git a/include/pbbam/internal/QueryBase.inl b/include/pbbam/internal/QueryBase.inl new file mode 100644 index 0000000..49cf860 --- /dev/null +++ b/include/pbbam/internal/QueryBase.inl @@ -0,0 +1,122 @@ +// Author: Derek Barnett + +#include "pbbam/internal/QueryBase.h" + +namespace PacBio { +namespace BAM { +namespace internal { + +// ------------------- +// QueryIteratorBase +// ------------------- + +template +inline QueryIteratorBase::QueryIteratorBase(QueryBase& query) + : query_{&query} +{ ReadNext(); } + +template inline +bool QueryIteratorBase::operator==(const QueryIteratorBase& other) const +{ return query_ == other.query_; } + +template inline +bool QueryIteratorBase::operator!=(const QueryIteratorBase& other) const +{ return !(*this == other); } + +// ------------------- +// QueryIterator +// ------------------- + +template inline +QueryIterator::QueryIterator(QueryBase& query) + : QueryIteratorBase{query} +{ } + +template inline +T& QueryIterator::operator*() +{ return QueryIteratorBase::record_; } + +template inline +T* QueryIterator::operator->() +{ return &(operator*()); } + +template inline +QueryIterator& QueryIterator::operator++() +{ QueryIteratorBase::ReadNext(); return *this; } + +template inline +QueryIterator QueryIterator::operator++(int) +{ + QueryIterator result(*this); + ++(*this); + return result; +} + +// -------------------- +// QueryConstIterator +// -------------------- + +template inline +QueryConstIterator::QueryConstIterator(const QueryBase& query) + : QueryIteratorBase{const_cast&>(query)} +{ } + +template inline +const T& QueryConstIterator::operator*() const +{ return QueryIteratorBase::record_; } + +template inline +const T* QueryConstIterator::operator->() const +{ return &(operator*()); } + +template inline +QueryConstIterator& QueryConstIterator::operator++() +{ QueryIteratorBase::ReadNext(); return *this; } + +template inline +QueryConstIterator QueryConstIterator::operator++(int) +{ + QueryConstIterator result(*this); + ++(*this); + return result; +} + +// ----------- +// QueryBase +// ----------- + +template inline +QueryConstIterator QueryBase::begin() const +{ return QueryConstIterator(*this); } + +template inline +QueryIterator QueryBase::begin() +{ return QueryIterator(*this); } + +template inline +QueryConstIterator QueryBase::cbegin() const +{ return QueryConstIterator(*this); } + +template inline +QueryConstIterator QueryBase::cend() const +{ return QueryConstIterator(); } + +template inline +QueryConstIterator QueryBase::end() const +{ return QueryConstIterator(); } + +template inline +QueryIterator QueryBase::end() +{ return QueryIterator(); } + +template +inline void QueryIteratorBase::ReadNext() +{ + assert(query_); + if (!query_->GetNext(record_)) + query_ = nullptr; +} + +} // namespace internal +} // namespace BAM +} // namespace PacBio diff --git a/include/pbbam/vcf/VcfFile.h b/include/pbbam/vcf/VcfFile.h new file mode 100644 index 0000000..8d6c356 --- /dev/null +++ b/include/pbbam/vcf/VcfFile.h @@ -0,0 +1,32 @@ +// Author: Derek Barnett + +#ifndef PBBAM_VCF_VCFFILE_H +#define PBBAM_VCF_VCFFILE_H + +#include "pbbam/Config.h" + +#include + +#include + +namespace PacBio { +namespace VCF { + +class VcfFile +{ +public: + explicit VcfFile(std::string fn); + +public: + const std::string& Filename() const; + const VcfHeader& Header() const; + +private: + std::string filename_; + VcfHeader header_; +}; + +} // namespace VCF +} // namespace PacBio + +#endif // PBBAM_VCF_VCFFILE_H diff --git a/include/pbbam/vcf/VcfFormat.h b/include/pbbam/vcf/VcfFormat.h new file mode 100644 index 0000000..b6885ee --- /dev/null +++ b/include/pbbam/vcf/VcfFormat.h @@ -0,0 +1,107 @@ +// Author: Derek Barnett + +#ifndef PBBAM_VCF_VCFFORMAT_H +#define PBBAM_VCF_VCFFORMAT_H + +#include "pbbam/Config.h" + +#include +#include + +#include +#include + +namespace PacBio { +namespace VCF { + +struct VcfFormat +{ +public: + /// \name General format info + /// \{ + + static const char* CurrentVersion(); + + /// \} + +public: + /// \name Header format + /// \{ + + static VcfHeader ParsedHeader(const std::string& text); + + static std::string FormattedHeader(const VcfHeader& header); + + static VcfHeader HeaderFromFile(const std::string& fn); + + static VcfHeader HeaderFromStream(std::istream& in); + + /// \} + +public: + /// \name Variant format + /// \{ + + static VcfVariant ParsedVariant(const std::string& line); + + static std::string FormattedVariant(const VcfVariant& var); + + /// \} + + // ---------------------------------------------------------------------- // + // The following methods are mostly internal helpers, exposed here for // + // testing. Client code should probably not need these, but are available // + // here if needed. // + // ---------------------------------------------------------------------- // + +public: + /// \internal + /// \name Header format helpers + /// \{ + + static ContigDefinition ParsedContigDefinition(std::string line); + + static FilterDefinition ParsedFilterDefinition(std::string line); + + static FormatDefinition ParsedFormatDefinition(std::string line); + + static GeneralDefinition ParsedGeneralDefinition(const std::string& line); + + static InfoDefinition ParsedInfoDefinition(std::string line); + + static std::string FormattedContigDefinition(const ContigDefinition& def); + + static std::string FormattedFilterDefinition(const FilterDefinition& def); + + static std::string FormattedFormatDefinition(const FormatDefinition& def); + + static std::string FormattedGeneralDefinition(const GeneralDefinition& def); + + static std::string FormattedInfoDefinition(const InfoDefinition& def); + + /// \} + +public: + /// \internal + /// \name Variant format helpers + /// \{ + + static std::string FormattedInfoField(const InfoField& field); + + static std::string FormattedInfoFields(const std::vector& fields); + + static std::string FormattedGenotypeField(const GenotypeField& field); + + static InfoField ParsedInfoField(const std::string& text); + + static std::vector ParsedInfoFields(const std::string& text); + + static GenotypeField ParsedGenotypeField(const std::string& field); + + /// \} +}; + +} // namespace VCF +} // namespace PacBio + +#endif // PBBAM_VCF_VCFFORMAT_H diff --git a/include/pbbam/vcf/VcfHeader.h b/include/pbbam/vcf/VcfHeader.h new file mode 100644 index 0000000..49bc62d --- /dev/null +++ b/include/pbbam/vcf/VcfHeader.h @@ -0,0 +1,115 @@ +// Author: Derek Barnett + +#ifndef PBBAM_VCF_VCFHEADER_H +#define PBBAM_VCF_VCFHEADER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include + +#include + +namespace PacBio { +namespace VCF { + +class VcfHeader +{ +public: + VcfHeader(); + + explicit VcfHeader(const std::string& hdrText); + +public: + // general lines + + size_t NumLines() const; + + const std::string& FileDate() const; + const std::string& Version() const; + + const std::vector& GeneralDefinitions() const; + const PacBio::VCF::GeneralDefinition& GeneralDefinition(const std::string& id) const; + + // ##contig + const std::vector& ContigDefinitions() const; + const PacBio::VCF::ContigDefinition& ContigDefinition(const std::string& id) const; + + // INFO + + const std::vector& InfoDefinitions() const; + const PacBio::VCF::InfoDefinition& InfoDefinition(const std::string& id) const; + + // FILTER + + const std::vector& FilterDefinitions() const; + const PacBio::VCF::FilterDefinition& FilterDefinition(const std::string& id) const; + + // FORMAT + + const std::vector& FormatDefinitions() const; + const PacBio::VCF::FormatDefinition& FormatDefinition(const std::string& id) const; + + // samples + + size_t IndexOfSample(const Sample& sample) const; + const Sample& SampleAt(size_t index) const; + const std::vector& Samples() const; + +public: + // general lines + + VcfHeader& FileDate(std::string fileDate); + VcfHeader& Version(std::string version); + + VcfHeader& AddGeneralDefinition(PacBio::VCF::GeneralDefinition def); + VcfHeader& GeneralDefinitions(std::vector defs); + + // ##contig + VcfHeader& AddContigDefinition(PacBio::VCF::ContigDefinition def); + VcfHeader& ContigDefinitions(std::vector defs); + + // INFO + + VcfHeader& AddInfoDefinition(PacBio::VCF::InfoDefinition info); + VcfHeader& InfoDefinitions(std::vector defs); + + // FILTER + + VcfHeader& AddFilterDefinition(PacBio::VCF::FilterDefinition filter); + VcfHeader& FilterDefinitions(std::vector defs); + + // FORMAT + + VcfHeader& AddFormatDefinition(PacBio::VCF::FormatDefinition format); + VcfHeader& FormatDefinitions(std::vector defs); + + // samples + + VcfHeader& AddSample(std::string sample); + VcfHeader& Samples(std::vector names); + +private: + std::vector generalDefinitions_; + std::vector contigDefinitions_; + std::vector infoDefinitions_; + std::vector filterDefinitions_; + std::vector formatDefinitions_; + std::vector samples_; + + std::unordered_map generalLookup_; + std::unordered_map contigLookup_; + std::unordered_map infoLookup_; + std::unordered_map filterLookup_; + std::unordered_map formatLookup_; + std::unordered_map sampleLookup_; +}; + +} // namespace VCF +} // namespace PacBio + +#endif // PBBAM_VCF_VCFHEADER_H diff --git a/include/pbbam/vcf/VcfHeaderTypes.h b/include/pbbam/vcf/VcfHeaderTypes.h new file mode 100644 index 0000000..9dd8fbf --- /dev/null +++ b/include/pbbam/vcf/VcfHeaderTypes.h @@ -0,0 +1,126 @@ + +#ifndef PBBAM_VCF_VCFHEADERTYPES_H +#define PBBAM_VCF_VCFHEADERTYPES_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +namespace PacBio { +namespace VCF { + +using Sample = std::string; + +class ContigDefinition +{ +public: + explicit ContigDefinition(std::string id); + ContigDefinition(std::string id, std::vector> attributes); + +public: + const std::string& Id() const; + const std::vector>& Attributes() const; + + ContigDefinition& AddAttribute(std::string id, std::string value); + ContigDefinition& AddAttribute(std::pair attribute); + ContigDefinition& Attributes(std::vector> attributes); + +private: + std::string id_; + std::vector> attributes_; +}; + +/// +/// \brief The FilterDefinition class +/// +class FilterDefinition +{ +public: + FilterDefinition(std::string id, std::string description); + + const std::string& Id() const; + const std::string& Description() const; + +private: + // required fields + std::string id_; + std::string description_; +}; + +/// +/// \brief The FormatDefinition class +/// +class FormatDefinition +{ +public: + FormatDefinition(std::string id, std::string number, std::string type, std::string description); + + const std::string& Id() const; + const std::string& Number() const; + const std::string& Type() const; + const std::string& Description() const; + +private: + std::string id_; + std::string number_; // TODO: enum + std::string type_; // TODO: enum + std::string description_; +}; + +/// +/// \brief The GeneralDefinition class +/// +class GeneralDefinition +{ +public: + GeneralDefinition(std::string id, std::string text); + + const std::string& Id() const; + const std::string& Text() const; + +private: + // required fields + std::string id_; + std::string text_; +}; + +/// +/// \brief The InfoDefinition class +/// +class InfoDefinition +{ +public: + InfoDefinition(std::string id, std::string number, std::string type, std::string description, + std::string source = std::string{}, std::string version = std::string{}); + + const std::string& Id() const; + const std::string& Number() const; + const std::string& Type() const; + const std::string& Description() const; + const boost::optional& Source() const; + const boost::optional& Version() const; + + InfoDefinition& Source(std::string s); + InfoDefinition& Version(std::string v); + +private: + // required fields + // (functionally const, not marked as such to still allow moves) + std::string id_; + std::string number_; // TODO: enum + std::string type_; // TODO: enum + std::string description_; + + // optional fields - settable after ctor + boost::optional source_; + boost::optional version_; +}; + +} // namespace VCF +} // namespace PacBio + +#endif // PBBAM_VCF_VCFHEADERTYPES_H diff --git a/include/pbbam/vcf/VcfQuery.h b/include/pbbam/vcf/VcfQuery.h new file mode 100644 index 0000000..c0c8a6d --- /dev/null +++ b/include/pbbam/vcf/VcfQuery.h @@ -0,0 +1,40 @@ +// Author: Derek Barnett + +#ifndef PBBAM_VCF_VCFQUERY_H +#define PBBAM_VCF_VCFQUERY_H + +#include "pbbam/Config.h" + +#include + +#include +#include +#include + +#include + +namespace PacBio { +namespace VCF { + +class VcfQuery : public PacBio::BAM::internal::QueryBase +{ +public: + explicit VcfQuery(std::string fn); + explicit VcfQuery(const VcfFile& file); + +public: + /// \brief Main iteration point for record access. + /// + /// Most client code should not need to use this method directly. Use + /// iterators instead. + /// + bool GetNext(VcfVariant& var) override; + +private: + VcfReader reader_; +}; + +} // namespace VCF +} // namespace PacBio + +#endif // PBBAM_VCF_VCFQUERY_H diff --git a/include/pbbam/vcf/VcfReader.h b/include/pbbam/vcf/VcfReader.h new file mode 100644 index 0000000..f4fbdbb --- /dev/null +++ b/include/pbbam/vcf/VcfReader.h @@ -0,0 +1,46 @@ +// Author: Derek Barnett + +#ifndef PBBAM_VCF_VCFREADER_H +#define PBBAM_VCF_VCFREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include +#include +#include + +namespace PacBio { +namespace VCF { + +/// +/// \brief The VcfReader class +/// +class VcfReader +{ +public: + explicit VcfReader(std::string fn); + explicit VcfReader(const VcfFile& file); + +public: + const VcfHeader& Header() const; + + bool GetNext(VcfVariant& var); + +private: + void FetchNext(); + +private: + std::ifstream in_; + VcfHeader header_; + std::string line_; +}; + +} // namespace VCF +} // namespace PacBio + +#endif // PBBAM_VCF_VCFREADER_H diff --git a/include/pbbam/vcf/VcfSort.h b/include/pbbam/vcf/VcfSort.h new file mode 100644 index 0000000..02c3aa1 --- /dev/null +++ b/include/pbbam/vcf/VcfSort.h @@ -0,0 +1,32 @@ +// Author: Derek Barnett + +#ifndef PBBAM_VCF_VCFSORT_H +#define PBBAM_VCF_VCFSORT_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/vcf/VcfFile.h" + +namespace PacBio { +namespace VCF { + +/// +/// \brief SortFile +/// \param file +/// \param outputFilename +/// +void SortFile(const VcfFile& file, const std::string& outputFilename); + +/// +/// \brief SortFile +/// \param inputFilename +/// \param outputFilename +/// +void SortFile(const std::string& inputFilename, const std::string& outputFilename); + +} // namespace VCF +} // namespace PacBio + +#endif // PBBAM_VCF_VCFSORT_H diff --git a/include/pbbam/vcf/VcfVariant.h b/include/pbbam/vcf/VcfVariant.h new file mode 100644 index 0000000..84f8ad7 --- /dev/null +++ b/include/pbbam/vcf/VcfVariant.h @@ -0,0 +1,146 @@ +// Author: Derek Barnett + +#ifndef PBBAM_VCF_VARIANT_H +#define PBBAM_VCF_VARIANT_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include + +#include +#include + +namespace PacBio { +namespace VCF { + +struct InfoField +{ + std::string id; + boost::optional value; + boost::optional> values; +}; + +struct GenotypeData +{ + boost::optional value; + boost::optional> values; +}; + +struct GenotypeField +{ + std::vector data; +}; + +class VcfVariant +{ +public: + VcfVariant(); + + explicit VcfVariant(const std::string& text); + + VcfVariant(std::string id, std::string chrom, PacBio::BAM::Position pos, std::string refAllele, + std::string altAllele); + +public: + // core fields + + const std::string& Chrom() const; + VcfVariant& Chrom(std::string chrom); + + PacBio::BAM::Position Position() const; + VcfVariant& Position(PacBio::BAM::Position pos); + + const std::string& Id() const; + VcfVariant& Id(std::string id); + + const std::string& RefAllele() const; + VcfVariant& RefAllele(std::string refAllele); + + const std::string& AltAllele() const; + VcfVariant& AltAllele(std::string altAllele); + + float Quality() const; + VcfVariant& Quality(float qual); + + const std::string& Filter() const; + VcfVariant& Filter(std::string filter); + + // convenience methods + bool IsDeletion() const; + bool IsInsertion() const; + bool IsQualityMissing() const; + bool IsSnp() const; + +public: + // info fields + + VcfVariant& AddInfoField(InfoField field); + VcfVariant& RemoveInfoField(const std::string& id); + + const std::vector& InfoFields() const; + VcfVariant& InfoFields(std::vector fields); + + bool HasInfoField(const std::string& id) const; + + const boost::optional InfoValue(const std::string& id) const; + VcfVariant& InfoValue(const std::string& id, boost::optional value); + + const boost::optional> InfoValues(const std::string& id) const; + VcfVariant& InfoValues(const std::string& id, boost::optional> values); + +public: + // sample genotypes + + // NOTE: if you want to look up by sample name, get the index from header + + std::vector GenotypeIds() const; + VcfVariant& GenotypeIds(std::vector ids); + + std::vector Genotypes() const; + VcfVariant& Genotypes(std::vector genotypes); + + const boost::optional& GenotypeValue(const size_t sampleIndex, + const std::string& id) const; + VcfVariant& GenotypeValue(const size_t sampleIndex, const std::string& id, + boost::optional value); + + const boost::optional>& GenotypeValues(const size_t sampleIndex, + const std::string& id) const; + VcfVariant& GenotypeValues(const size_t sampleIndex, const std::string& id, + boost::optional> values); + + bool IsSampleHeterozygous(const size_t sampleIndex) const; + bool IsSamplePhased(const size_t sampleIndex) const; + +private: + // FIXED data + std::string chrom_; + PacBio::BAM::Position pos_; + std::string id_; + std::string refAllele_; + std::string altAllele_; // multiple? KISS, only add if needed + float qual_; + std::string filter_; + + // INFO data + std::vector infoFields_; + std::unordered_map infoLookup_; + + // SAMPLE GENOTYPE data + std::vector format_; // order matches FORMAT string + std::unordered_map + genotypeDataLookup_; // genotype ID -> genotypeField.data index + std::vector sampleGenotypes_; // index matches sample order +}; + +} // namespace VCF +} // namespace PacBio + +// #include "pbbam/vcf/internal/VcfVariant.inl" + +#endif // PBBAM_VCF_VARIANT_H diff --git a/include/pbbam/vcf/VcfWriter.h b/include/pbbam/vcf/VcfWriter.h new file mode 100644 index 0000000..266d9a8 --- /dev/null +++ b/include/pbbam/vcf/VcfWriter.h @@ -0,0 +1,37 @@ +// Author: Derek Barnett + +#ifndef PBBAM_VCF_VCFWRITER_H +#define PBBAM_VCF_VCFWRITER_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace VCF { + +class VcfHeader; +class VcfVariant; + +class VcfWriter +{ +public: + VcfWriter(std::string filename, const VcfHeader& header); + + VcfWriter(VcfWriter&&) noexcept; + VcfWriter& operator=(VcfWriter&&) noexcept; + ~VcfWriter(); + +public: + bool Write(const VcfVariant& var); + +private: + struct VcfWriterPrivate; + std::unique_ptr d_; +}; + +} // namespace VCF +} // namespace PacBio + +#endif // PBBAM_VCF_VCFWRITER_H diff --git a/include/pbbam/virtual/VirtualPolymeraseBamRecord.h b/include/pbbam/virtual/VirtualPolymeraseBamRecord.h new file mode 100644 index 0000000..372fa99 --- /dev/null +++ b/include/pbbam/virtual/VirtualPolymeraseBamRecord.h @@ -0,0 +1,23 @@ +// File Description +/// \file VirtualPolymeraseBamRecord.h +/// \brief Defines the VirtualPolymeraseBamRecord class. +// +// Author: Armin Töpfer + +#ifndef VIRTUALPOLYMERASEBAMRECORD_H +#define VIRTUALPOLYMERASEBAMRECORD_H + +#include "pbbam/Config.h" + +#include "pbbam/virtual/VirtualZmwBamRecord.h" + +namespace PacBio { +namespace BAM { + +/// \deprecated Use VirtualZmwBamRecord instead. +using VirtualPolymeraseBamRecord = VirtualZmwBamRecord; + +} // namespace BAM +} // namespace PacBio + +#endif // VIRTUALPOLYMERASEBAMRECORD_H diff --git a/include/pbbam/virtual/VirtualPolymeraseCompositeReader.h b/include/pbbam/virtual/VirtualPolymeraseCompositeReader.h new file mode 100644 index 0000000..a1df56f --- /dev/null +++ b/include/pbbam/virtual/VirtualPolymeraseCompositeReader.h @@ -0,0 +1,23 @@ +// File Description +/// \file VirtualPolymeraseCompositeReader.h +/// \brief Defines the VirtualPolymeraseCompositeReader class. +// +// Author: Derek Barnett + +#ifndef VIRTUALPOLYMERASECOMPOSITEREADER_H +#define VIRTUALPOLYMERASECOMPOSITEREADER_H + +#include "pbbam/Config.h" + +#include "pbbam/virtual/ZmwReadStitcher.h" + +namespace PacBio { +namespace BAM { + +/// \deprecated Use ZmwReadStitcher instead. +using VirtualPolymeraseCompositeReader = ZmwReadStitcher; + +} // namespace BAM +} // namespace PacBio + +#endif // VIRTUALPOLYMERASECOMPOSITEREADER_H diff --git a/include/pbbam/virtual/VirtualPolymeraseReader.h b/include/pbbam/virtual/VirtualPolymeraseReader.h new file mode 100644 index 0000000..4c6a66e --- /dev/null +++ b/include/pbbam/virtual/VirtualPolymeraseReader.h @@ -0,0 +1,23 @@ +// File Description +/// \file VirtualPolymeraseReader.h +/// \brief Defines the VirtualPolymeraseReader class. +// +// Author: Armin Töpfer + +#ifndef VIRTUALPOLYMERASEREADER_H +#define VIRTUALPOLYMERASEREADER_H + +#include "pbbam/Config.h" + +#include "pbbam/virtual/ZmwReadStitcher.h" + +namespace PacBio { +namespace BAM { + +/// \deprecated Use ZmwReadStitcher instead. +using VirtualPolymeraseReader = ZmwReadStitcher; + +} // namespace BAM +} // namespace PacBio + +#endif // VIRTUALPOLYMERASEREADER_H diff --git a/include/pbbam/virtual/VirtualRegion.h b/include/pbbam/virtual/VirtualRegion.h new file mode 100644 index 0000000..c56d6bb --- /dev/null +++ b/include/pbbam/virtual/VirtualRegion.h @@ -0,0 +1,50 @@ +// File Description +/// \file VirtualRegion.h +/// \brief Defines the VirtualRegion class. +// +// Author: Armin Töpfer + +#ifndef VIRTUALREGION_H +#define VIRTUALREGION_H + +#include "pbbam/Config.h" + +#include "pbbam/LocalContextFlags.h" +#include "pbbam/virtual/VirtualRegionType.h" + +namespace PacBio { +namespace BAM { + +/// \brief The VirtualRegion represents an annotation of a polymerase region. +/// +class VirtualRegion +{ +public: + VirtualRegionType type; + int beginPos; + int endPos; + LocalContextFlags cxTag = LocalContextFlags::NO_LOCAL_CONTEXT; + int barcodeLeft = -1; + int barcodeRight = -1; + int score = 0; + + /// \brief Creates a virtual region with basic type & position info. + /// + VirtualRegion(const VirtualRegionType type_, const int beginPos_, const int endPos_, + const int score_ = 0); + + /// \brief Creates a virtual region with type/position info, as well as context & barcode. + /// + VirtualRegion(const VirtualRegionType type_, const int beginPos_, const int endPos_, + const LocalContextFlags cxTag_, const int barcodeLeft_, const int barcodeRight_, + const int score_ = 0); + + VirtualRegion() = default; + + bool operator==(const VirtualRegion& v1) const; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // VIRTUALREGION_H diff --git a/include/pbbam/virtual/VirtualRegionType.h b/include/pbbam/virtual/VirtualRegionType.h new file mode 100644 index 0000000..c23d3ee --- /dev/null +++ b/include/pbbam/virtual/VirtualRegionType.h @@ -0,0 +1,30 @@ +// File Description +/// \file VirtualRegionType.h +/// \brief Defines the VirtualRegionType enum. +// +// Author: Derek Barnett + +#ifndef REGIONTYPE_H +#define REGIONTYPE_H + +#include "pbbam/Config.h" + +namespace PacBio { +namespace BAM { + +/// \brief This enum defines the types of annotated region. +/// +enum class VirtualRegionType // : char +{ + ADAPTER = 0x41, ///< Adapter region ('A') + BARCODE = 0x42, ///< Barcode region ('B') + FILTERED = 0x46, ///< Filtered subread ('F') + SUBREAD = 0x53, ///< Subread ('S') + HQREGION = 0x48, ///< High-quality region ('H') + LQREGION = 0x4C ///< Low-quality region ('L'), i.e. outside the HQ region +}; + +} // namespace BAM +} // namespace PacBio + +#endif // REGIONTYPE_H diff --git a/include/pbbam/virtual/VirtualRegionTypeMap.h b/include/pbbam/virtual/VirtualRegionTypeMap.h new file mode 100644 index 0000000..d770a35 --- /dev/null +++ b/include/pbbam/virtual/VirtualRegionTypeMap.h @@ -0,0 +1,31 @@ +// File Description +/// \file VirtualRegionTypeMap.h +/// \brief Defines the VirtualRegionTypeMap class. +// +// Author: Derek Barnett + +#ifndef VIRTUALREGIONTYPEMAP_H +#define VIRTUALREGIONTYPEMAP_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/virtual/VirtualRegionType.h" + +namespace PacBio { +namespace BAM { + +/// \brief The VirtualRegionTypeMap class provides mapping between char codes and +/// VirtualRegionType enum keys. +/// +class VirtualRegionTypeMap +{ +public: + static std::map ParseChar; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // VIRTUALREGIONTYPEMAP_H diff --git a/include/pbbam/virtual/VirtualZmwBamRecord.h b/include/pbbam/virtual/VirtualZmwBamRecord.h new file mode 100644 index 0000000..0fb1965 --- /dev/null +++ b/include/pbbam/virtual/VirtualZmwBamRecord.h @@ -0,0 +1,78 @@ +// File Description +/// \file VirtualZmwBamRecord.h +/// \brief Defines the VirtualZmwBamRecord class. +// +// Author: Armin Töpfer + +#ifndef VirtualZmwBAMRECORD_H +#define VirtualZmwBAMRECORD_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/virtual/VirtualRegion.h" +#include "pbbam/virtual/VirtualRegionType.h" + +namespace PacBio { +namespace BAM { + +/// \brief The VirtualZmwBamRecord class represents a ZMW read stitched +/// on-the-fly from subreads|hqregion + scraps. +/// +class VirtualZmwBamRecord : public BamRecord +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates a "virtual" ZMW %BAM record, by re-stitching its + /// constituent segments. + /// + /// \param[in] unorderedSources source data (subreads, scraps, etc.) + /// \param[in] header %BAM header to associate with the new record + /// + /// \throws std::runtime_error on failure to stitch virtual record + /// + VirtualZmwBamRecord(std::vector unorderedSources, const BamHeader& header); + + /// \} + + /// \name Virtual Record Attributes + /// + + /// \returns true if requested VirtualRegionType has been annotated. + /// + bool HasVirtualRegionType(const VirtualRegionType regionType) const; + + /// \returns IPD frame data + /// + Frames IPDV1Frames(Orientation orientation = Orientation::NATIVE) const; + + /// \brief Provides all annotations of the polymerase read as a map (type => regions) + /// + std::map> VirtualRegionsMap() const; + + /// \brief Provides annotations of the polymerase read for a given VirtualRegionType. + /// + /// \param[in] regionType requested region type + /// \returns regions that match the requested type (empty vector if none found). + /// + std::vector VirtualRegionsTable(const VirtualRegionType regionType) const; + + /// \} + +private: + std::vector sources_; + std::map> virtualRegionsMap_; + + void StitchSources(); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // VirtualZmwBAMRECORD_H diff --git a/include/pbbam/virtual/WhitelistedZmwReadStitcher.h b/include/pbbam/virtual/WhitelistedZmwReadStitcher.h new file mode 100644 index 0000000..c5272f5 --- /dev/null +++ b/include/pbbam/virtual/WhitelistedZmwReadStitcher.h @@ -0,0 +1,103 @@ +// File Description +/// \file WhitelistedZmwReadStitcher.h +/// \brief Defines the ZmwReadStitcher class. +// +// Author: Derek Barnett + +#ifndef WHITELISTEDZMWREADSTITCHER_H +#define WHITELISTEDZMWREADSTITCHER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include "pbbam/virtual/VirtualZmwBamRecord.h" + +namespace PacBio { +namespace BAM { + +class DataSet; +class PbiFilter; + +/// \brief The WhitelistedZmwReadStitcher class provides an interface for +/// re-stitching "virtual" ZMW reads from their constituent parts, +/// limiting results to only those reads originating from a 'whitelist' +/// of ZMW hole numbers. +/// +/// Whitelisted ZMWs that are not present in both primary and scraps BAMs +/// will be "pre-removed." This ensures that, given client code like this: +/// +/// \include code/WhitelistedZmwReadStitcher.txt +/// +/// each iteration will always provide valid data - either a valid virtual +/// record from Next() or a non-empty vector from NextRaw(). +/// +/// \note This reader requires that both input %BAM files also have associated +/// PBI files available for query. See BamFile::EnsurePacBioIndexExists . +/// +class PBBAM_EXPORT WhitelistedZmwReadStitcher +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// \brief Creates a reader that will operate on a primary %BAM file (e.g. subread data) + /// and a scraps file, using a ZMW whitelist to filter the input. + /// + /// \param[in] zmwWhitelist list of ZMWs to restrict iteration over + /// \param[in] primaryBamFilePath hqregion.bam or subreads.bam file path + /// \param[in] scrapsBamFilePath scraps.bam file path + /// + /// \note This reader requires that both input %BAM files also have associated PBI + /// files available for query. See BamFile::EnsurePacBioIndexExists . + /// + /// \throws std::runtime_error if any files (*.bam and/or *.pbi) were not available for reading, or + /// if malformed data encountered + /// + WhitelistedZmwReadStitcher(const std::vector& zmwWhitelist, + const std::string& primaryBamFilePath, + const std::string& scrapsBamFilePath); + + ~WhitelistedZmwReadStitcher(); + + /// \} + + /// \name Stitched Record Reading + /// \{ + + /// \returns true if more ZMWs are available for reading. + bool HasNext() const; + + /// \returns the re-stitched polymerase read from the next ZMW in the whitelist + VirtualZmwBamRecord Next(); + + /// \returns the set of reads that belong to the next ZMW in the whitelist. + /// This enables stitching records in a distinct thread. + /// + std::vector NextRaw(); + + /// \} + + /// \name File Headers + /// \{ + + /// \returns the BamHeader associated with this reader's "primary" %BAM file + BamHeader PrimaryHeader() const; + + /// \returns the BamHeader associated with this reader's "scraps" %BAM file + BamHeader ScrapsHeader() const; + + /// \} + +private: + class WhitelistedZmwReadStitcherPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // WHITELISTEDZMWREADSTITCHER diff --git a/include/pbbam/virtual/ZmwReadStitcher.h b/include/pbbam/virtual/ZmwReadStitcher.h new file mode 100644 index 0000000..711cfa7 --- /dev/null +++ b/include/pbbam/virtual/ZmwReadStitcher.h @@ -0,0 +1,89 @@ +// File Description +/// \file ZmwReadStitcher.h +/// \brief Defines the ZmwReadStitcher class. +// +// Author: Derek Barnett + +#ifndef ZMWREADSTITCHER_H +#define ZMWREADSTITCHER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include "pbbam/BamRecord.h" +#include "pbbam/virtual/VirtualZmwBamRecord.h" + +namespace PacBio { +namespace BAM { + +class DataSet; +class PbiFilter; + +/// \brief The ZmwReadStitcher class provides an interface for re-stitching +/// "virtual" polymerase reads from their constituent parts. +/// +/// \note This reader requires that any input %BAM files also have associated PBI +/// files available for query. See BamFile::EnsurePacBioIndexExists . +/// +class PBBAM_EXPORT ZmwReadStitcher +{ +public: + /// \name Constructors & Related Methods + /// \{ + + /// entire file, from BAM names + ZmwReadStitcher(std::string primaryBamFilePath, std::string scrapsBamFilePath); + + /// filtered input from BAM names + ZmwReadStitcher(std::string primaryBamFilePath, std::string scrapsBamFilePath, + PbiFilter filter); + + /// maybe filtered, from DataSet input + ZmwReadStitcher(const DataSet& dataset); + + ~ZmwReadStitcher(); + + /// \} + + /// \name File Headers + /// \{ + + /// \returns the BamHeader associated with this reader's "primary" %BAM file + BamHeader PrimaryHeader() const; + + /// \returns the BamHeader associated with this reader's "scraps" %BAM file + BamHeader ScrapsHeader() const; + + /// \return the BamHeader associated with the newly stitched BAM data + BamHeader StitchedHeader() const; + + /// \} + + /// \name Stitched Record Reading + /// + + /// \returns true if more ZMWs are available for reading. + bool HasNext(); + + /// \returns the next stitched polymerase read + VirtualZmwBamRecord Next(); + + /// \returns the next set of reads that belong to one ZMW. + /// This enables stitching records in a distinct thread. + /// + std::vector NextRaw(); + + /// \} + +private: + class ZmwReadStitcherPrivate; + std::unique_ptr d_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWREADSTITCHER_H diff --git a/include/pbbam/virtual/ZmwWhitelistVirtualReader.h b/include/pbbam/virtual/ZmwWhitelistVirtualReader.h new file mode 100644 index 0000000..af1ab7c --- /dev/null +++ b/include/pbbam/virtual/ZmwWhitelistVirtualReader.h @@ -0,0 +1,23 @@ +// File Description +/// \file ZmwWhitelistVirtualReader.h +/// \brief Defines the ZmwWhitelistVirtualReader class. +// +// Author: Derek Barnett + +#ifndef ZMWWHITELISTVIRTUALREADER_H +#define ZMWWHITELISTVIRTUALREADER_H + +#include "pbbam/Config.h" + +#include "pbbam/virtual/WhitelistedZmwReadStitcher.h" + +namespace PacBio { +namespace BAM { + +/// \deprecated Use WhitelistedZmwReadStitcher instead. +using ZmwWhitelistVirtualReader = WhitelistedZmwReadStitcher; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWWHITELISTVIRTUALREADER_H diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..7dc4ec2 --- /dev/null +++ b/meson.build @@ -0,0 +1,140 @@ +project( + 'PacBioBAM', + 'cpp', + version : '1.0.6', + default_options : [ + 'buildtype=release', + 'warning_level=3', + 'cpp_std=c++14', + 'b_ndebug=if-release'], + license : 'BSD-3', + meson_version : '>= 0.46.0') + +############ +# CXXFLAGS # +############ + +pbbam_warning_flags = [] +cpp = meson.get_compiler('cpp') +foreach cflag: [ + '-Wduplicated-cond', + '-Wduplicated-branches', + '-Wlogical-op', + '-Wrestrict', + '-Wnull-dereference', + '-Wuseless-cast', + '-Wdouble-promotion', + '-Wshadow', + '-Wformat=1'] + if cpp.has_argument(cflag) + pbbam_warning_flags += cflag + endif +endforeach + +pbbam_macros = [] +if get_option('permissive-cigar') + pbbam_macros += ['-DPBBAM_PERMISSIVE_CIGAR'] + warning('**********************************************') + warning('* You have enabled allowing "M" in BAM files *') + warning('* This is an unsupported combination! *') + warning('**********************************************') +endif + +################ +# dependencies # +################ + +# threads +pbbam_thread_dep = dependency('threads', required : true) + +# boost +pbbam_boost_dep = dependency('boost', required : true) + +# TODO(dseifert): Add test for Winsock on Windows +# Winsock for htslib on Windows +#if(WIN32) +# set(SOCKET_LIBRARIES "ws2_32") +#endif() + +# zlib +pbbam_zlib_dep = dependency('zlib', required : true, fallback : ['zlib', 'zlib_dep']) + +# htslib +pbbam_htslib_dep = dependency('htslib', required : true, version : '>=1.4', fallback : ['htslib', 'htslib_dep']) + +# pbcopper +pbbam_pbcopper_dep = dependency('pbcopper', required : true, fallback : ['pbcopper', 'pbcopper_dep']) + +########### +# headers # +########### + +subdir('include') + +##################### +# sources + library # +##################### + +subdir('src') + +######### +# tests # +######### + +if not meson.is_subproject() + if get_option('build-tools') or get_option('tests') + pbbam_python = find_program('python') + + if get_option('tests') + pbbam_clang_formatter = find_program('tools/check-formatting') + subdir('tests') + endif + endif +endif + +######### +# tools # +######### + +if not meson.is_subproject() + if get_option('build-tools') or get_option('tests') + subdir('tools') + endif +endif + +################# +# documentation # +################# + +if get_option('build-docs') + subdir('docs') +endif + +################### +# dependency info # +################### + +if not meson.is_subproject() + # need to add pbcopper into 'Requires:' field, + # but Meson currently only allows this if it's a + # 'pkgconfig-dependency object' and not a subproject + pbbam_requires = [] + if pbbam_pbcopper_dep.type_name() == 'pkgconfig' + pbbam_requires = [pbbam_pbcopper_dep] + endif + + import('pkgconfig').generate( + pbbam_lib, + version : meson.project_version(), + name : 'pbbam', + requires : pbbam_requires, + filebase : 'pbbam', + description : 'Library for accessing PacBio-compatible BAM files') +endif + +pbbam_dep = declare_dependency( + include_directories : pbbam_include_directories, + link_with : pbbam_lib, + dependencies : [pbbam_htslib_dep, pbbam_pbcopper_dep], + version : meson.project_version(), + compile_args : pbbam_macros) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..56dbe36 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,24 @@ +option('build-tools', + type : 'boolean', + value : true, + description : 'Build PacBioBAM command line utilities (e.g. pbindex)') + +option('build-docs', + type : 'boolean', + value : false, + description : 'Build PacBioBAM\'s API documentation') + +option('auto-validate', + type : 'boolean', + value : false, + description : 'Build PacBioBAM with BAM validation') + +option('tests', + type : 'boolean', + value : true, + description : 'Enable dependencies required for testing') + +option('permissive-cigar', + type : 'boolean', + value : false, + description : 'Allows loading BAM records which contain "M" operations in CIGAR strings.') diff --git a/scripts/ci/artifact.sh b/scripts/ci/artifact.sh new file mode 100755 index 0000000..7a2268c --- /dev/null +++ b/scripts/ci/artifact.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -vex + +############ +# ARTIFACT # +############ + +if [[ ${_create_artifact} != true ]]; then + echo "Not creating artifact (branch: ${bamboo_planRepository_branchName}), returning." + return 0 +fi + +# *never* create artifacts with ASAN enabled +meson configure -Dprefix=/ -Db_sanitize=none "${CURRENT_BUILD_DIR:-build}" + +NEXUS_VERSION="$(${CURRENT_BUILD_DIR:-build}/tools/pbindex --version | grep -o -E '[[:digit:]]+(\.[[:digit:]]+)*')".${BUILD_NUMBER} +case "${bamboo_planRepository_branchName}" in + develop) + VERSION="$(${CURRENT_BUILD_DIR:-build}/tools/pbindex --version | grep -o -E '[[:digit:]]+(\.[[:digit:]]+)*')".SNAPSHOT${BUILD_NUMBER} + NEXUS_REPO=maven-snapshots + ;; + master) + VERSION="${NEXUS_VERSION}" + NEXUS_REPO=maven-releases + ;; + *) + echo "You can only create artifacts from 'develop' or 'master' branches" + exit 1 + ;; +esac + +DESTDIR="${PWD}/staging" ninja -C "${CURRENT_BUILD_DIR:-build}" -v install + +# merge pbcopper and pbbam for PA +pushd "${PWD}/staging/lib" + # GNU ld MRI script trick + # https://stackoverflow.com/a/23621751 + echo "create libnew.a" >libnew.mri + for i in libpb*.a; do + echo "addlib ${i}" >>libnew.mri + done + echo save >>libnew.mri + echo end >>libnew.mri + ar -M | pbbam-${VERSION}-x86_64.tgz.md5 +sha1sum pbbam-${VERSION}-x86_64.tgz | awk -e '{print $1}' >| pbbam-${VERSION}-x86_64.tgz.sha1 + +NEXUS_URL=http://ossnexus.pacificbiosciences.com/repository/${NEXUS_REPO}/${NEXUS_PROJECT:-pacbio/sat/pbbam/pbbam}/${NEXUS_VERSION:-gcc-6.4.0}${NEXUS_TC} +curl -vn --upload-file pbbam-${VERSION}-x86_64.tgz ${NEXUS_URL}/pbbam-${VERSION}-x86_64.tgz +curl -vn --upload-file pbbam-${VERSION}-x86_64.tgz.md5 ${NEXUS_URL}/pbbam-${VERSION}-x86_64.tgz.md5 +curl -vn --upload-file pbbam-${VERSION}-x86_64.tgz.sha1 ${NEXUS_URL}/pbbam-${VERSION}-x86_64.tgz.sha1 diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh new file mode 100755 index 0000000..b1d7459 --- /dev/null +++ b/scripts/ci/build.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +set -vex + +######### +# BUILD # +######### + +# on PA, need to first build pbcopper+htslib +if [[ ${GCC_VERSION} == PA ]]; then + pushd _deps/pbcopper + meson \ + --default-library static \ + --libdir lib \ + --wrap-mode nofallback \ + --prefix "${bamboo_build_working_directory}/staging" \ + -Dtests=false \ + build . + ninja -C build -v install + popd + + wget https://github.com/samtools/htslib/releases/download/1.9/htslib-1.9.tar.bz2 + tar -xjf htslib-1.9.tar.bz2 + pushd htslib-1.9 + CFLAGS="-O3" ./configure \ + --prefix="${bamboo_build_working_directory}/staging" \ + --libdir="${bamboo_build_working_directory}/staging/lib" \ + --disable-bz2 \ + --disable-gcs \ + --disable-libcurl \ + --disable-lzma \ + --disable-plugins \ + --disable-s3 + + make -j install + + # clean out unneeded cruft and shared libs, + # as -lhts will prefer shared libraries + rm -rf ${bamboo_build_working_directory}/staging/{bin,share} + rm -f ${bamboo_build_working_directory}/staging/lib/*.so* + + # set pkg-config variables + export PKG_CONFIG_LIBDIR+=":${bamboo_build_working_directory}/staging/lib/pkgconfig" + + # convert `-I` to `-isystem` in pkg-config file in order not to trigger -Werror + sed -e 's/-I/-isystem/g' -i "${bamboo_build_working_directory}/staging/lib/pkgconfig/htslib.pc" + popd +fi + +# configure +# '--wrap-mode nofallback' prevents meson from downloading +# stuff from the internet or using subprojects. +meson \ + --werror \ + --buildtype "${BUILDTYPE:-release}" \ + --default-library "${LIBRARYTYPE:-shared}" \ + --libdir lib \ + --unity "${ENABLED_UNITY_BUILD:-off}" \ + --wrap-mode nofallback \ + --prefix "${PREFIX_ARG:-/}" \ + -Db_coverage="${ENABLED_COVERAGE:-false}" \ + -Db_sanitize="${ENABLED_SANITIZERS:-none}" \ + -Dtests="${ENABLED_TESTS:-false}" \ + "${CURRENT_BUILD_DIR:-build}" . + +# build +ninja -C "${CURRENT_BUILD_DIR:-build}" -v diff --git a/scripts/ci/install.sh b/scripts/ci/install.sh new file mode 100755 index 0000000..7bf937b --- /dev/null +++ b/scripts/ci/install.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -vex + +########### +# INSTALL # +########### + +if [[ ${_install_image} != true ]]; then + echo "Not installing image (branch: ${bamboo_planRepository_branchName}), returning." + return 0 +fi + +if [[ ${PREFIX_ARG} ]]; then + ## Cleaning out old installation from /mnt/software + rm -rf "${PREFIX_ARG}"/* +fi + +# *never* install with ASAN enabled +meson configure -Db_sanitize=none "${CURRENT_BUILD_DIR:-build}" + +DESTDIR="${DESTDIR:-/}" ninja -C "${CURRENT_BUILD_DIR:-build}" -v install diff --git a/scripts/ci/setup.sh b/scripts/ci/setup.sh new file mode 100755 index 0000000..a01bdcc --- /dev/null +++ b/scripts/ci/setup.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +set -vex + +export ENABLED_TESTS="true" + +case "${bamboo_planRepository_branchName}" in + master) + _pbcopper_module="pbcopper/master" + ;; + *) + _pbcopper_module="pbcopper/develop" + ;; +esac + +case "${GCC_VERSION}" in + next) + module load gcc/8.1.0 + module load gtest + module load ${_pbcopper_module} + ;; + + PA) + # have to build htslib for PA + module unload htslib + module load zlib + module load gtest/gcc48 + + # load SCL GCC + source /opt/rh/devtoolset-6/enable + + export NEXUS_PROJECT=pacbio/seq/pa/pbbam + export NEXUS_TC="" + export _artifact_versionprepend="true" + ;; + + *) + module load gcc + module load gtest + module load ${_pbcopper_module} + ;; +esac + +module load ccache + +export CC="ccache gcc" +export CXX="ccache g++" +export CCACHE_BASEDIR="${PWD}" + +if [[ -z ${bamboo_planRepository_branchName+x} ]]; then + : #pass +elif [[ ! -d /pbi/flash/bamboo/ccachedir ]]; then + echo "[WARNING] /pbi/flash/bamboo/ccachedir is missing" +elif [[ $bamboo_planRepository_branchName == develop ]]; then + export CCACHE_DIR=/pbi/flash/bamboo/ccachedir/${bamboo_shortPlanKey}.${bamboo_shortJobKey}.develop + export CCACHE_TEMPDIR=/scratch/bamboo.ccache_tempdir +elif [[ $bamboo_planRepository_branchName == master ]]; then + export CCACHE_DIR=/pbi/flash/bamboo/ccachedir/${bamboo_shortPlanKey}.${bamboo_shortJobKey}.master + export CCACHE_TEMPDIR=/scratch/bamboo.ccache_tempdir +elif [[ $USER == bamboo ]]; then + _shortPlanKey=$(echo ${bamboo_shortPlanKey}|sed -e 's/[0-9]*$//') + export CCACHE_DIR=/pbi/flash/bamboo/ccachedir/${bamboo_shortPlanKey}.${bamboo_shortJobKey} + if [[ -d /pbi/flash/bamboo/ccachedir/${_shortPlanKey}.${bamboo_shortJobKey}.develop ]]; then + ( cd /pbi/flash/bamboo/ccachedir/ + cp -a ${_shortPlanKey}.${bamboo_shortJobKey}.develop $CCACHE_DIR + ) + fi + export CCACHE_TEMPDIR=/scratch/bamboo.ccache_tempdir +fi diff --git a/scripts/ci/test.sh b/scripts/ci/test.sh new file mode 100755 index 0000000..3abbd6c --- /dev/null +++ b/scripts/ci/test.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -vex + +######## +# TEST # +######## + +ninja -C "${CURRENT_BUILD_DIR:-build}" -v test + +############ +# COVERAGE # +############ + +if [[ ${ENABLED_COVERAGE:-false} == true ]]; then + module load gcov + + pushd "${CURRENT_BUILD_DIR:-build}" + find . -type f -iname '*.o' | xargs gcov -acbrfu {} \; >/dev/null && \ + mkdir coverage && pushd coverage && mv ../*.gcov . && \ + sed -i -e 's@Source:@Source:../@' *.gcov && \ + sed -i -e 's@Graph:@Graph:../@' *.gcov && \ + sed -i -e 's@Data:@Data:../@' *.gcov && \ + rm pugixml* && popd + popd +fi diff --git a/src/AlignmentPrinter.cpp b/src/AlignmentPrinter.cpp new file mode 100644 index 0000000..b55736c --- /dev/null +++ b/src/AlignmentPrinter.cpp @@ -0,0 +1,131 @@ +// File Description +/// \file AlignmentPrinter.cpp +/// \brief Implements the AlignmentPrinter class. +// +// Author: Armin Töpfer + +#include "PbbamInternalConfig.h" + +#include "pbbam/AlignmentPrinter.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "AlignmentPrinter(const AlignmentPrinter&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "AlignmentPrinter& operator=(const AlignmentPrinter&) is not = delete"); + +static_assert(std::is_nothrow_move_constructible::value, + "AlignmentPrinter(AlignmentPrinter&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "AlignmentPrinter& operator=(AlignmentPrinter&&) is not = noexcept"); + +AlignmentPrinter::AlignmentPrinter(const IndexedFastaReader& ifr) + : ifr_{std::make_unique(ifr)} +{ +} + +std::string AlignmentPrinter::Print(const BamRecord& record, const Orientation orientation) +{ + const std::string seq{record.Sequence(orientation, true, true)}; + const std::string ref{ifr_->ReferenceSubsequence(record, orientation, true, true)}; + + if (seq.size() != ref.size()) { + std::ostringstream s; + s << "AlignmentPrinter: sequence and reference lengths are not equal:\n" + << " seq: " << seq.size() << '\n' + << " ref: " << ref.size(); + throw std::runtime_error{s.str()}; + } + + int seqLength = 0; + float matches = 0; + std::string pretty; + Position refCoord = record.ReferenceStart(); + Position seqCoord = BAM::IsCcsOrTranscript(record.Type()) ? 0 : record.QueryStart(); + + for (size_t i = 0; i < seq.size();) { + auto refCoordStr = std::to_string(refCoord); + auto seqCoordStr = std::to_string(seqCoord); + + size_t maxCoordLength = std::max(refCoordStr.size(), seqCoordStr.size()); + while (refCoordStr.size() < maxCoordLength) + refCoordStr = " " + refCoordStr; + while (seqCoordStr.size() < maxCoordLength) + seqCoordStr = " " + seqCoordStr; + + std::string seqWrap{seqCoordStr + " : "}; + std::string refWrap{refCoordStr + " : "}; + std::string prettyWrap(maxCoordLength + 3, ' '); + prettyWrap.reserve(seq.size()); + + // clang-format off + for (int j = 0; i < seq.size() && j < 40; ++i, ++j) { + refWrap += ref[i]; + + if (seq[i] == ref[i]) { + ++matches; + if (refCoord == 0 || refCoord % 10) + prettyWrap += '|'; + else { + prettyWrap += "\033" "[1m" "\x1b" "[31m"; + prettyWrap += '|'; + prettyWrap += "\033" "[0m" "\x1b" "[39;49m"; + } + seqWrap += seq[i]; + } else if (seq[i] == '-' || ref[i] == '-') { + prettyWrap += ' '; + seqWrap += seq[i]; + } else { + prettyWrap += '.'; + seqWrap += "\033" "[1m" "\x1b" "[31m"; + seqWrap += seq[i]; + seqWrap += "\033" "[0m" "\x1b" "[39;49m"; + } + if (seq[i] != '-') { + ++seqLength; + ++seqCoord; + } + if (ref[i] != '-') { + ++refCoord; + } + } + // clang-format on + + refCoordStr = std::to_string(refCoord); + seqCoordStr = std::to_string(seqCoord); + + maxCoordLength = std::max(refCoordStr.size(), seqCoordStr.size()); + while (refCoordStr.size() < maxCoordLength) + refCoordStr = " " + refCoordStr; + while (seqCoordStr.size() < maxCoordLength) + seqCoordStr = " " + seqCoordStr; + + seqWrap += " : " + seqCoordStr; + refWrap += " : " + refCoordStr; + + pretty += refWrap + '\n' + prettyWrap + '\n' + seqWrap + "\n\n"; + } + const float similarity = matches / seq.size(); + + std::stringstream output; + output << "Read : " << record.FullName() << '\n' + << "Reference : " << record.ReferenceName() << "\n\n" + << "Read-length : " << seqLength << '\n' + << "Concordance : " << std::setprecision(3) << (similarity) << "\n\n" + << pretty; + return output.str(); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/Autovalidate.h b/src/Autovalidate.h new file mode 100644 index 0000000..098c691 --- /dev/null +++ b/src/Autovalidate.h @@ -0,0 +1,24 @@ +// File Description +/// \file Autovalidate.h +/// \brief Sets the default macro for the autovalidation mode. +// +// Author: Derek Barnett + +#ifndef AUTOVALIDATE_H +#define AUTOVALIDATE_H + +#include "pbbam/Config.h" + +// \brief Auto-validation +// +// To validate BAM components (header, records, etc.) you can either use the +// Validator API provided, or enable auto-validation. To compile pbbam for +// auto-validation, add the -Dauto-validate=true option to your Meson +// invocation. +// +// +#ifndef PBBAM_AUTOVALIDATE +#define PBBAM_AUTOVALIDATE 0 +#endif + +#endif // AUTOVALIDATE_H diff --git a/src/BaiIndexCache.cpp b/src/BaiIndexCache.cpp new file mode 100644 index 0000000..8ea9bc8 --- /dev/null +++ b/src/BaiIndexCache.cpp @@ -0,0 +1,73 @@ +// File Description +/// \file BaiIndexCache.cpp +/// \brief Implements the BaiIndexCache class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BaiIndexCache.h" + +#include + +#include + +#include "MemoryUtils.h" +#include "pbbam/BamFile.h" +#include "pbbam/DataSet.h" + +namespace PacBio { +namespace BAM { + +struct BaiIndexCacheData::BaiIndexCacheDataPrivate +{ + using IndexType = std::unique_ptr; + IndexType htsIndex_; +}; + +BaiIndexCacheData::BaiIndexCacheData(const BamFile& bamFile) : BaiIndexCacheData(bamFile.Filename()) +{ +} + +BaiIndexCacheData::BaiIndexCacheData(const std::string& bamFilename) + : d_{std::make_unique()} +{ + d_->htsIndex_.reset(bam_index_load(bamFilename.c_str())); + if (!d_->htsIndex_) { + throw std::runtime_error{"BaiIndexCache: could not load *.bai index data for file: " + + bamFilename}; + } +} + +BaiIndexCacheData::~BaiIndexCacheData() = default; + +hts_itr_t* BaiIndexCacheData::IteratorForInterval(const int32_t refId, const Position start, + const Position stop) const +{ + return bam_itr_queryi(d_->htsIndex_.get(), refId, start, stop); +} + +using BaiIndexCache = std::shared_ptr>>; + +BaiIndexCache MakeBaiIndexCache(const DataSet& dataset) +{ + return MakeBaiIndexCache(dataset.BamFiles()); +} + +BaiIndexCache MakeBaiIndexCache(const std::vector& bamFiles) +{ + BaiIndexCache cache = std::make_shared>>(); + auto& indices = *cache.get(); + for (const auto& bamFile : bamFiles) + indices.push_back(std::make_shared(bamFile)); + return cache; +} + +BaiIndexCache MakeBaiIndexCache(const BamFile& bamFile) +{ + std::vector bamFiles{bamFile}; + return MakeBaiIndexCache(bamFiles); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BaiIndexedBamReader.cpp b/src/BaiIndexedBamReader.cpp new file mode 100644 index 0000000..fd62b1e --- /dev/null +++ b/src/BaiIndexedBamReader.cpp @@ -0,0 +1,141 @@ +// File Description +/// \file BaiIndexedBamReader.cpp +/// \brief Implements the BaiIndexedBamReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BaiIndexedBamReader.h" + +#include +#include +#include +#include + +#include "MemoryUtils.h" +#include "pbbam/BaiIndexCache.h" + +namespace PacBio { +namespace BAM { + +class BaiIndexedBamReader::BaiIndexedBamReaderPrivate +{ +public: + BaiIndexedBamReaderPrivate(BamFile file, const std::shared_ptr& index) + : file_{std::move(file)}, index_{index} + { + if (!index_) index_ = std::make_shared(file_); + assert(index_); // should throw in cache load if failed + } + + BaiIndexedBamReaderPrivate(BamFile file, const GenomicInterval& interval, + const std::shared_ptr& indexCache) + : BaiIndexedBamReaderPrivate{std::move(file), indexCache} + { + Interval(file_.Header(), interval); + } + + void Interval(const BamHeader& header, const GenomicInterval& interval) + { + htsIterator_.reset(); + + if (header.HasSequence(interval.Name())) { + auto id = header.SequenceId(interval.Name()); + if (id >= 0 && static_cast(id) < header.NumSequences()) { + htsIterator_.reset( + index_->IteratorForInterval(id, interval.Start(), interval.Stop())); + } + } + + if (!htsIterator_) { + std::ostringstream s; + s << "BaiIndexedBamReader: could not create iterator for requested region: " + << interval.Name() << " [" << interval.Start() << ", " << interval.Stop() << ')'; + throw std::runtime_error{s.str()}; + } + } + + int ReadRawData(BGZF* bgzf, bam1_t* b) + { + assert(htsIterator_.get()); + return hts_itr_next(bgzf, htsIterator_.get(), b, nullptr); + } + + BamFile file_; + std::shared_ptr index_; + GenomicInterval interval_; + std::unique_ptr htsIterator_; +}; + +BaiIndexedBamReader::BaiIndexedBamReader(std::string filename) + : BaiIndexedBamReader{BamFile{std::move(filename)}, nullptr} +{ +} + +BaiIndexedBamReader::BaiIndexedBamReader(std::string filename, + const std::shared_ptr& index) + : BaiIndexedBamReader{BamFile{std::move(filename)}, index} +{ +} + +BaiIndexedBamReader::BaiIndexedBamReader(BamFile bamFile) + : BamReader{bamFile.Filename()} + , d_{std::make_unique(std::move(bamFile), nullptr)} +{ +} + +BaiIndexedBamReader::BaiIndexedBamReader(BamFile bamFile, + const std::shared_ptr& index) + : BamReader{bamFile.Filename()} + , d_{std::make_unique(std::move(bamFile), index)} +{ +} + +BaiIndexedBamReader::BaiIndexedBamReader(const GenomicInterval& interval, std::string filename) + : BaiIndexedBamReader{interval, BamFile{std::move(filename)}, nullptr} +{ +} + +BaiIndexedBamReader::BaiIndexedBamReader(const GenomicInterval& interval, std::string filename, + const std::shared_ptr& index) + : BaiIndexedBamReader{interval, BamFile{std::move(filename)}, index} +{ +} + +BaiIndexedBamReader::BaiIndexedBamReader(const GenomicInterval& interval, BamFile bamFile) + : BamReader{bamFile.Filename()} + , d_{std::make_unique(std::move(bamFile), interval, nullptr)} +{ +} + +BaiIndexedBamReader::BaiIndexedBamReader(const GenomicInterval& interval, BamFile bamFile, + const std::shared_ptr& index) + : BamReader{bamFile.Filename()} + , d_{std::make_unique(std::move(bamFile), interval, index)} +{ +} + +const BamFile& BaiIndexedBamReader::File() const { return d_->file_; } + +const GenomicInterval& BaiIndexedBamReader::Interval() const +{ + assert(d_); + return d_->interval_; +} + +int BaiIndexedBamReader::ReadRawData(BGZF* bgzf, bam1_t* b) +{ + assert(d_); + return d_->ReadRawData(bgzf, b); +} + +BaiIndexedBamReader& BaiIndexedBamReader::Interval(const GenomicInterval& interval) +{ + assert(d_); + d_->Interval(Header(), interval); + return *this; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamFile.cpp b/src/BamFile.cpp new file mode 100644 index 0000000..a6bac47 --- /dev/null +++ b/src/BamFile.cpp @@ -0,0 +1,194 @@ +// File Description +/// \file BamFile.cpp +/// \brief Implements the BamFile class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamFile.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "Autovalidate.h" +#include "FileUtils.h" +#include "MemoryUtils.h" +#include "pbbam/PbiFile.h" + +namespace PacBio { +namespace BAM { + +class BamFile::BamFilePrivate +{ +public: + explicit BamFilePrivate(std::string fn) : filename_{std::move(fn)}, firstAlignmentOffset_{-1} + { + // ensure we've updated htslib verbosity with requested verbosity here + hts_verbose = (PacBio::BAM::HtslibVerbosity == -1 ? 0 : PacBio::BAM::HtslibVerbosity); + + // attempt open + auto f = RawOpen(); + +#if !defined(PBBAM_NO_CHECK_EOF) || PBBAM_AUTOVALIDATE + // sanity check on file + const auto eofCheck = bgzf_check_EOF(f->fp.bgzf); + if (eofCheck <= 0) { + // 1: EOF present & correct + // 2: not seekable (e.g. reading from stdin) + // 0: EOF absent + // -1: some other error + std::ostringstream e; + if (eofCheck == 0) + e << "BamFile: missing EOF block in " << fn; + else + e << "BamFile: unknown error encountered while checking EOF in " << fn + << " (status code = " << eofCheck << ')'; + throw std::runtime_error{e.str()}; + } +#endif + + // attempt fetch header + std::unique_ptr hdr(sam_hdr_read(f.get())); + header_ = BamHeaderMemory::FromRawData(hdr.get()); + + // cache first alignment offset + firstAlignmentOffset_ = bgzf_tell(f->fp.bgzf); + } + + std::unique_ptr DeepCopy() + { + return std::make_unique(filename_); + } + + bool HasEOF() const + { + // streamed input is unknown, since it's not random-accessible + if (filename_ == "-") return false; + + // attempt open + auto f = RawOpen(); + return RawEOFCheck(f) == 1; + } + + int RawEOFCheck(const std::unique_ptr& f) const + { + assert(f); + assert(f->fp.bgzf); + return bgzf_check_EOF(f->fp.bgzf); + } + + std::unique_ptr RawOpen() const + { + std::unique_ptr f(sam_open(filename_.c_str(), "rb")); + if (!f || !f->fp.bgzf) throw std::runtime_error{"BamFile: could not open: " + filename_}; + if (f->format.format != bam) + throw std::runtime_error{"BamFile: expected BAM, encountered un supported format: " + + filename_}; + return f; + } + + std::string filename_; + BamHeader header_; + int64_t firstAlignmentOffset_; +}; + +BamFile::BamFile(std::string filename) : d_{std::make_unique(std::move(filename))} +{ +} + +BamFile::BamFile(const BamFile& other) : d_{other.d_->DeepCopy()} {} + +BamFile::BamFile(BamFile&&) noexcept = default; + +BamFile& BamFile::operator=(const BamFile& other) +{ + if (this != &other) { + d_ = other.d_->DeepCopy(); + } + return *this; +} + +BamFile& BamFile::operator=(BamFile&&) noexcept = default; + +BamFile::~BamFile() = default; + +void BamFile::CreatePacBioIndex() const { PbiFile::CreateFrom(*this); } + +void BamFile::CreateStandardIndex() const +{ + const auto ret = bam_index_build(d_->filename_.c_str(), 0); + if (ret != 0) { + std::ostringstream s; + s << "BamFile: could not create *.bai index for file: " << d_->filename_ + << " (status code = " << ret << ')'; + throw std::runtime_error{s.str()}; + } +} + +void BamFile::EnsurePacBioIndexExists() const +{ + if (!PacBioIndexExists()) CreatePacBioIndex(); +} + +void BamFile::EnsureStandardIndexExists() const +{ + if (!StandardIndexExists()) CreateStandardIndex(); +} + +const std::string& BamFile::Filename() const { return d_->filename_; } + +int64_t BamFile::FirstAlignmentOffset() const { return d_->firstAlignmentOffset_; } + +bool BamFile::HasEOF() const { return d_->HasEOF(); } + +bool BamFile::HasReference(const std::string& name) const { return d_->header_.HasSequence(name); } + +const BamHeader& BamFile::Header() const { return d_->header_; } + +bool BamFile::IsPacBioBAM() const { return !d_->header_.PacBioBamVersion().empty(); } + +bool BamFile::PacBioIndexExists() const { return FileUtils::Exists(PacBioIndexFilename()); } + +std::string BamFile::PacBioIndexFilename() const { return d_->filename_ + ".pbi"; } + +bool BamFile::PacBioIndexIsNewer() const +{ + const auto bamTimestamp = FileUtils::LastModified(Filename()); + const auto pbiTimestamp = FileUtils::LastModified(PacBioIndexFilename()); + return bamTimestamp <= pbiTimestamp; +} + +int BamFile::ReferenceId(const std::string& name) const { return d_->header_.SequenceId(name); } + +uint32_t BamFile::ReferenceLength(const std::string& name) const +{ + return ReferenceLength(ReferenceId(name)); +} + +uint32_t BamFile::ReferenceLength(const int id) const +{ + return std::stoul(d_->header_.SequenceLength(id)); +} + +std::string BamFile::ReferenceName(const int id) const { return d_->header_.SequenceName(id); } + +bool BamFile::StandardIndexExists() const { return FileUtils::Exists(StandardIndexFilename()); } + +std::string BamFile::StandardIndexFilename() const { return d_->filename_ + ".bai"; } + +bool BamFile::StandardIndexIsNewer() const +{ + const auto bamTimestamp = FileUtils::LastModified(Filename()); + const auto baiTimestamp = FileUtils::LastModified(StandardIndexFilename()); + return bamTimestamp <= baiTimestamp; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamFileMerger.cpp b/src/BamFileMerger.cpp new file mode 100644 index 0000000..b246619 --- /dev/null +++ b/src/BamFileMerger.cpp @@ -0,0 +1,260 @@ +// File Description +/// \file BamFileMerger.cpp +/// \brief Implements the BamFileMerger & helper classes. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamFileMerger.h" + +#include +#include +#include +#include +#include + +#include "pbbam/BamFile.h" +#include "pbbam/BamHeader.h" +#include "pbbam/BamReader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/CompositeBamReader.h" +#include "pbbam/DataSet.h" +#include "pbbam/IRecordWriter.h" +#include "pbbam/IndexedBamWriter.h" +#include "pbbam/PbiBuilder.h" +#include "pbbam/PbiFilter.h" +#include "pbbam/PbiIndexedBamReader.h" +#include "pbbam/RecordType.h" + +namespace PacBio { +namespace BAM { +namespace { // anonymous + +using CompositeMergeItem = internal::CompositeMergeItem; + +struct QNameSorter +{ + bool operator()(const CompositeMergeItem& lhs, const CompositeMergeItem& rhs) const + { + const BamRecord& l = lhs.record; + const BamRecord& r = rhs.record; + + // movie name + std::string lMovieName, rMovieName; // TODO(CD): memoize movienames? + try { + lMovieName = l.MovieName(); + } catch (std::runtime_error const& err) { + std::ostringstream s; + s << "BamFileMerger: could not get movie name from file: " << lhs.reader->Filename() + << " (reason = " << err.what() << ')'; + throw std::runtime_error(s.str()); + } + try { + rMovieName = r.MovieName(); + } catch (std::runtime_error const& err) { + std::ostringstream s; + s << "BamFileMerger: could not get movie name from file: " << rhs.reader->Filename() + << " (reason = " << err.what() << ')'; + throw std::runtime_error(s.str()); + } + const int cmp = lMovieName.compare(rMovieName); + if (cmp != 0) return cmp < 0; + + // hole number + const auto lhsZmw = l.HoleNumber(); + const auto rhsZmw = r.HoleNumber(); + if (lhsZmw != rhsZmw) return lhsZmw < rhsZmw; + + // shuffle CCS/transcript reads after all others + if (IsCcsOrTranscript(l.Type())) return false; + if (IsCcsOrTranscript(r.Type())) return true; + + // sort on qStart, then finally qEnd + const auto lhsQStart = l.QueryStart(); + const auto rhsQStart = r.QueryStart(); + if (lhsQStart != rhsQStart) return lhsQStart < rhsQStart; + + const auto lhsQEnd = l.QueryEnd(); + const auto rhsQEnd = r.QueryEnd(); + return lhsQEnd < rhsQEnd; + } +}; + +class ICollator +{ +public: + virtual bool GetNext(BamRecord&) = 0; + virtual ~ICollator() = default; + +protected: + ICollator() = default; +}; + +template +class CollatorImpl : public ICollator +{ +public: + CollatorImpl(std::vector> readers) : ICollator() + { + for (auto&& reader : readers) { + auto item = CompositeMergeItem{std::move(reader)}; + if (item.reader->GetNext(item.record)) mergeItems_.insert(std::move(item)); + } + } + + bool GetNext(BamRecord& record) override + { + if (mergeItems_.empty()) return false; + + // Move first record into our result + auto& firstItem = const_cast(*mergeItems_.begin()); + auto& firstRecord = firstItem.record; + std::swap(record, firstRecord); + + // Try to read next record from current reader. If available, re-insert + // into the set. Otherwise, just drop it (dtor will release resource). + CompositeMergeItem tmp(std::move(firstItem)); + mergeItems_.erase(mergeItems_.begin()); + if (tmp.reader->GetNext(tmp.record)) mergeItems_.insert(std::move(tmp)); + return true; + } + +private: + std::multiset mergeItems_; +}; + +using QNameCollator = CollatorImpl; +using AlignedCollator = CollatorImpl; + +std::vector> MakeBamReaders(std::vector bamFiles, + PbiFilter filter = PbiFilter{}) +{ + std::vector> readers; + for (auto& file : bamFiles) { + if (filter.IsEmpty()) + readers.emplace_back(std::make_unique(std::move(file))); + else + readers.emplace_back(std::make_unique(filter, std::move(file))); + } + assert(!readers.empty()); + return readers; +} + +std::unique_ptr MakeCollator(std::vector> readers, + const bool isCoordinateSorted = false) +{ + std::unique_ptr collator; + if (isCoordinateSorted) + collator = std::make_unique(std::move(readers)); + else + collator = std::make_unique(std::move(readers)); + return collator; +} + +std::unique_ptr MakeBamWriter(const std::vector>& readers, + const std::string& outputFilename, + const bool createPbi, const ProgramInfo& pgInfo) +{ + if (outputFilename.empty()) + throw std::runtime_error{"BamFileMerger: no output filename provided"}; + + // read headers + std::vector headers; + for (const auto& reader : readers) + headers.push_back(reader->Header()); + assert(!headers.empty()); + + // merge headers + BamHeader mergedHeader = headers.at(0); + const std::string usingSortOrder = mergedHeader.SortOrder(); + for (size_t i = 1; i < headers.size(); ++i) { + const auto& header = headers.at(i); + if (header.SortOrder() != usingSortOrder) + throw std::runtime_error{ + "BamFileMerger: BAM file sort orders do not match, aborting merge"}; + mergedHeader += header; + } + + // maybe add program info + if (pgInfo.IsValid()) mergedHeader.AddProgram(pgInfo); + + // create BAM writer (PBI-on-the-fly?) + if (createPbi) + return std::make_unique(outputFilename, mergedHeader); + else + return std::make_unique(outputFilename, mergedHeader); +} + +} // namespace anonymous + +void BamFileMerger::Merge(const std::vector& bamFilenames, + const std::string& outputFilename, bool createPbi, + const ProgramInfo& pgInfo) +{ + std::vector bamFiles; + for (const auto& fn : bamFilenames) + bamFiles.emplace_back(fn); + + auto readers = MakeBamReaders(std::move(bamFiles)); + const bool isCoordinateSorted = readers.front()->Header().SortOrder() == "coordinate"; + + auto writer = MakeBamWriter(readers, outputFilename, createPbi, pgInfo); + auto collator = MakeCollator(std::move(readers), isCoordinateSorted); + + BamRecord record; + while (collator->GetNext(record)) + writer->Write(record); +} + +void BamFileMerger::Merge(const DataSet& dataset, const std::string& outputFilename, bool createPbi, + const ProgramInfo& pgInfo) +{ + std::vector bamFiles = dataset.BamFiles(); + if (bamFiles.empty()) throw std::runtime_error{"BamFileMerger: no input filenames provided"}; + + auto readers = MakeBamReaders(std::move(bamFiles), PbiFilter::FromDataSet(dataset)); + const bool isCoordinateSorted = readers.front()->Header().SortOrder() == "coordinate"; + + auto writer = MakeBamWriter(readers, outputFilename, createPbi, pgInfo); + auto collator = MakeCollator(std::move(readers), isCoordinateSorted); + + BamRecord record; + while (collator->GetNext(record)) + writer->Write(record); +} + +void BamFileMerger::Merge(const std::vector& bamFilenames, IRecordWriter& writer) +{ + std::vector bamFiles; + for (const auto& fn : bamFilenames) + bamFiles.emplace_back(fn); + if (bamFiles.empty()) throw std::runtime_error{"BamFileMerger: no input filenames provided"}; + + auto readers = MakeBamReaders(std::move(bamFiles)); + const bool isCoordinateSorted = readers.front()->Header().SortOrder() == "coordinate"; + + auto collator = MakeCollator(std::move(readers), isCoordinateSorted); + + BamRecord record; + while (collator->GetNext(record)) + writer.Write(record); +} + +void BamFileMerger::Merge(const DataSet& dataset, IRecordWriter& writer) +{ + std::vector bamFiles = dataset.BamFiles(); + if (bamFiles.empty()) throw std::runtime_error{"BamFileMerger: no input filenames provided"}; + + auto readers = MakeBamReaders(std::move(bamFiles), PbiFilter::FromDataSet(dataset)); + const bool isCoordinateSorted = readers.front()->Header().SortOrder() == "coordinate"; + + auto collator = MakeCollator(std::move(readers), isCoordinateSorted); + + BamRecord record; + while (collator->GetNext(record)) + writer.Write(record); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamHeader.cpp b/src/BamHeader.cpp new file mode 100644 index 0000000..7a8bbc6 --- /dev/null +++ b/src/BamHeader.cpp @@ -0,0 +1,453 @@ +// File Description +/// \file BamHeader.cpp +/// \brief Implements the BamHeader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamHeader.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "Version.h" +#include "pbbam/SamTagCodec.h" +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { +namespace { + +const std::string BamHeaderPrefixHD{"@HD"}; +const std::string BamHeaderPrefixSQ{"@SQ"}; +const std::string BamHeaderPrefixRG{"@RG"}; +const std::string BamHeaderPrefixPG{"@PG"}; +const std::string BamHeaderPrefixCO{"@CO"}; + +const std::string BamHeaderTokenVN{"VN"}; +const std::string BamHeaderTokenSO{"SO"}; +const std::string BamHeaderTokenpb{"pb"}; + +bool CheckSortOrder(const std::string& lhs, const std::string& rhs) { return lhs == rhs; } + +bool CheckPbVersion(const std::string& lhs, const std::string& rhs) +{ + using Version = PacBio::BAM::Version; + + return (Version{lhs} >= Version::Minimum && Version{rhs} >= Version::Minimum); +} + +bool CheckSequences(const std::string& sortOrder, const std::vector& lhs, + const std::vector& rhs) +{ + return ((sortOrder == "coordinate") ? lhs == rhs : true); +} + +static void EnsureCanMerge(const BamHeader& lhs, const BamHeader& rhs) +{ + // check compatibility + const auto sortOrderOk = CheckSortOrder(lhs.SortOrder(), rhs.SortOrder()); + const auto pbVersionOk = CheckPbVersion(lhs.PacBioBamVersion(), rhs.PacBioBamVersion()); + const auto sequencesOk = CheckSequences(lhs.SortOrder(), lhs.Sequences(), rhs.Sequences()); + if (sortOrderOk && pbVersionOk && sequencesOk) return; + + // if any checks failed, format error message & throw + std::ostringstream e; + e << "BamHeader: could not merge headers:\n"; + + if (!sortOrderOk) { + e << " mismatched sort orders (@HD:SO) : (" << lhs.SortOrder() << ", " << rhs.SortOrder() + << ")\n"; + } + + if (!pbVersionOk) { + e << " incompatible PacBio BAM versions (@HD:pb) : (" << lhs.PacBioBamVersion() << ", " + << rhs.PacBioBamVersion() << ")\n"; + } + + if (!sequencesOk) e << " mismatched sequence lists (@SQ entries)\n"; + + throw std::runtime_error{e.str()}; +} + +void ParseHeaderLine(const std::string& line, BamHeader& hdr) +{ + // pop off '@HD\t', then split HD lines into tokens + const auto tokens = Split(line.substr(4), '\t'); + for (const auto& token : tokens) { + const auto tokenTag = token.substr(0, 2); + const auto tokenValue = token.substr(3); + + // set header contents + if (tokenTag == BamHeaderTokenVN) + hdr.Version(tokenValue); + else if (tokenTag == BamHeaderTokenSO) + hdr.SortOrder(tokenValue); + else if (tokenTag == BamHeaderTokenpb) + hdr.PacBioBamVersion(tokenValue); + } +} + +} // anonymous + +static_assert(std::is_copy_constructible::value, + "BamHeader(const BamHeader&) is not = default"); +static_assert(std::is_copy_assignable::value, + "BamHeader& operator=(const BamHeader&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "BamHeader(BamHeader&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "BamHeader& operator=(BamHeader&&) is not = noexcept"); + +class BamHeader::BamHeaderPrivate +{ +public: + std::string version_; + std::string pacbioBamVersion_; + std::string sortOrder_; + std::map headerLineCustom_; + + std::map readGroups_; // id => read group info + std::map programs_; // id => program info + std::vector comments_; + + // we need to preserve insertion order, use lookup for access by name + std::vector sequences_; + std::map sequenceIdLookup_; +}; + +BamHeader::BamHeader() : d_{std::make_shared()} {} + +BamHeader::BamHeader(const std::string& samHeaderText) : d_{std::make_shared()} +{ + std::istringstream s{samHeaderText}; + std::string line; + std::string firstToken; + while (std::getline(s, line)) { + + // skip if line is not long enough to contain true values + if (line.length() < 5) continue; + + // determine token at beginning of line + firstToken = line.substr(0, 3); + + if (firstToken == BamHeaderPrefixHD) { + ParseHeaderLine(line, *this); + if (Version().empty()) Version(std::string{hts_version()}); + } + + else if (firstToken == BamHeaderPrefixSQ) + AddSequence(SequenceInfo::FromSam(line)); + + else if (firstToken == BamHeaderPrefixRG) + AddReadGroup(ReadGroupInfo::FromSam(line)); + + else if (firstToken == BamHeaderPrefixPG) + AddProgram(ProgramInfo::FromSam(line)); + + else if (firstToken == BamHeaderPrefixCO) + AddComment(line.substr(4)); + } +} + +BamHeader& BamHeader::operator+=(const BamHeader& other) +{ + EnsureCanMerge(*this, other); + + // merge read groups + for (const auto& rg : other.ReadGroups()) { + if (!HasReadGroup(rg.Id())) AddReadGroup(rg); + } + + // merge programs + for (const auto& pg : other.Programs()) { + if (!HasProgram(pg.Id())) AddProgram(pg); + } + + // merge comments + for (const auto& comment : other.Comments()) + AddComment(comment); + + return *this; +} + +BamHeader BamHeader::operator+(const BamHeader& other) const { return DeepCopy() += other; } + +BamHeader& BamHeader::AddComment(std::string comment) +{ + d_->comments_.push_back(std::move(comment)); + return *this; +} + +BamHeader& BamHeader::AddProgram(ProgramInfo pg) +{ + d_->programs_[pg.Id()] = std::move(pg); + return *this; +} + +BamHeader& BamHeader::AddReadGroup(ReadGroupInfo readGroup) +{ + d_->readGroups_[readGroup.Id()] = std::move(readGroup); + return *this; +} + +BamHeader& BamHeader::AddSequence(SequenceInfo sequence) +{ + const std::string name = sequence.Name(); + d_->sequences_.push_back(std::move(sequence)); + d_->sequenceIdLookup_[name] = d_->sequences_.size() - 1; + return *this; +} + +BamHeader& BamHeader::ClearComments() +{ + d_->comments_.clear(); + return *this; +} + +BamHeader& BamHeader::ClearPrograms() +{ + d_->programs_.clear(); + return *this; +} + +BamHeader& BamHeader::ClearReadGroups() +{ + d_->readGroups_.clear(); + return *this; +} + +BamHeader& BamHeader::ClearSequences() +{ + d_->sequenceIdLookup_.clear(); + d_->sequences_.clear(); + return *this; +} + +std::vector BamHeader::Comments() const { return d_->comments_; } + +BamHeader& BamHeader::Comments(std::vector comments) +{ + d_->comments_ = std::move(comments); + return *this; +} + +BamHeader BamHeader::DeepCopy() const +{ + BamHeader result; + result.d_->version_ = d_->version_; + result.d_->pacbioBamVersion_ = d_->pacbioBamVersion_; + result.d_->sortOrder_ = d_->sortOrder_; + result.d_->headerLineCustom_ = d_->headerLineCustom_; + result.d_->readGroups_ = d_->readGroups_; + result.d_->programs_ = d_->programs_; + result.d_->comments_ = d_->comments_; + result.d_->sequences_ = d_->sequences_; + result.d_->sequenceIdLookup_ = d_->sequenceIdLookup_; + return result; +} + +bool BamHeader::HasProgram(const std::string& id) const +{ + return d_->programs_.find(id) != d_->programs_.cend(); +} + +bool BamHeader::HasReadGroup(const std::string& id) const +{ + return d_->readGroups_.find(id) != d_->readGroups_.cend(); +} + +bool BamHeader::HasSequence(const std::string& name) const +{ + return d_->sequenceIdLookup_.find(name) != d_->sequenceIdLookup_.cend(); +} + +size_t BamHeader::NumSequences() const { return d_->sequences_.size(); } + +std::string BamHeader::PacBioBamVersion() const { return d_->pacbioBamVersion_; } + +BamHeader& BamHeader::PacBioBamVersion(const std::string& version) +{ + d_->pacbioBamVersion_ = version; + const PacBio::BAM::Version fileVersion{version}; + if (fileVersion < Version::Minimum) { + throw std::runtime_error{ + "BamHeader: invalid PacBio BAM version number (" + fileVersion.ToString() + + ") is older than the minimum supported version (" + Version::Minimum.ToString() + ")"}; + } + return *this; +} + +ProgramInfo BamHeader::Program(const std::string& id) const +{ + const auto iter = d_->programs_.find(id); + if (iter == d_->programs_.cend()) + throw std::runtime_error{"BamHeader: program ID not found: " + id}; + return iter->second; +} + +std::vector BamHeader::ProgramIds() const +{ + std::vector result; + result.reserve(d_->programs_.size()); + for (const auto& pg : d_->programs_) + result.push_back(pg.first); + return result; +} + +std::vector BamHeader::Programs() const +{ + std::vector result; + result.reserve(d_->programs_.size()); + for (const auto& pg : d_->programs_) + result.push_back(pg.second); + return result; +} + +BamHeader& BamHeader::Programs(std::vector programs) +{ + d_->programs_.clear(); + for (const auto& pg : programs) + d_->programs_[pg.Id()] = std::move(pg); + return *this; +} + +ReadGroupInfo BamHeader::ReadGroup(const std::string& id) const +{ + const auto iter = d_->readGroups_.find(id); + if (iter == d_->readGroups_.cend()) + throw std::runtime_error{"BamHeader: read group ID not found: " + id}; + return iter->second; +} + +std::vector BamHeader::ReadGroupIds() const +{ + std::vector result; + result.reserve(d_->readGroups_.size()); + for (const auto& rg : d_->readGroups_) + result.push_back(rg.first); + return result; +} + +std::vector BamHeader::ReadGroups() const +{ + std::vector result; + result.reserve(d_->readGroups_.size()); + for (const auto& rg : d_->readGroups_) + result.push_back(rg.second); + return result; +} + +BamHeader& BamHeader::ReadGroups(std::vector readGroups) +{ + d_->readGroups_.clear(); + for (auto&& rg : readGroups) + d_->readGroups_[rg.Id()] = std::move(rg); + return *this; +} + +SequenceInfo BamHeader::Sequence(const int32_t id) const { return d_->sequences_.at(id); } + +SequenceInfo BamHeader::Sequence(const std::string& name) const +{ + // TODO: SequenceId(name) throws if not found, should we do so here as well? + + const auto iter = d_->sequenceIdLookup_.find(name); + if (iter == d_->sequenceIdLookup_.cend()) return SequenceInfo(); + const auto index = iter->second; + assert(index >= 0 && static_cast(index) < d_->sequences_.size()); + return d_->sequences_.at(index); +} + +int32_t BamHeader::SequenceId(const std::string& name) const +{ + const auto iter = d_->sequenceIdLookup_.find(name); + if (iter == d_->sequenceIdLookup_.cend()) + throw std::runtime_error{"BamHeader: sequence name not found: " + name}; + return iter->second; +} + +std::string BamHeader::SequenceLength(const int32_t id) const { return Sequence(id).Length(); } + +std::string BamHeader::SequenceName(const int32_t id) const { return Sequence(id).Name(); } + +std::vector BamHeader::SequenceNames() const +{ + std::vector result; + result.reserve(d_->sequences_.size()); + for (const auto& seq : d_->sequences_) + result.push_back(seq.Name()); + return result; +} + +std::vector BamHeader::Sequences() const { return d_->sequences_; } + +BamHeader& BamHeader::Sequences(std::vector sequences) +{ + d_->sequences_.clear(); + for (auto&& seq : sequences) + AddSequence(std::move(seq)); + return *this; +} + +std::string BamHeader::SortOrder() const { return d_->sortOrder_; } + +BamHeader& BamHeader::SortOrder(std::string order) +{ + d_->sortOrder_ = std::move(order); + return *this; +} + +std::string BamHeader::ToSam() const +{ + // init stream + std::ostringstream out; + + // @HD + const auto outputVersion = (d_->version_.empty() ? std::string{hts_version()} : d_->version_); + const auto outputSortOrder = (d_->sortOrder_.empty() ? std::string{"unknown"} : d_->sortOrder_); + const auto outputPbBamVersion = + (d_->pacbioBamVersion_.empty() ? Version::Current.ToString() : d_->pacbioBamVersion_); + + out << BamHeaderPrefixHD << MakeSamTag(BamHeaderTokenVN, outputVersion) + << MakeSamTag(BamHeaderTokenSO, outputSortOrder) + << MakeSamTag(BamHeaderTokenpb, outputPbBamVersion) << '\n'; + + // @SQ + for (const auto& seq : d_->sequences_) + out << seq.ToSam() << '\n'; + + // @RG + for (const auto& rgIter : d_->readGroups_) + out << rgIter.second.ToSam() << '\n'; + + // @PG + for (const auto& progIter : d_->programs_) + out << progIter.second.ToSam() << '\n'; + + // @CO + for (const auto& comment : d_->comments_) + out << BamHeaderPrefixCO << '\t' << comment << '\n'; + + // return result + return out.str(); +} + +std::string BamHeader::Version() const { return d_->version_; } + +BamHeader& BamHeader::Version(std::string version) +{ + d_->version_ = std::move(version); + return *this; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamReader.cpp b/src/BamReader.cpp new file mode 100644 index 0000000..7f454fd --- /dev/null +++ b/src/BamReader.cpp @@ -0,0 +1,115 @@ +// File Description +/// \file BamReader.cpp +/// \brief Implements the BamReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamReader.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Autovalidate.h" +#include "MemoryUtils.h" +#include "pbbam/Validator.h" + +namespace PacBio { +namespace BAM { + +class BamReader::BamReaderPrivate +{ +public: + explicit BamReaderPrivate(std::string fn) : filename_{std::move(fn)} + { + htsFile_.reset(sam_open(filename_.c_str(), "rb")); + if (!htsFile_ || !htsFile_->fp.bgzf) { + throw std::runtime_error{"BamReader: could not open BAM file for reading: " + + filename_}; + } + + std::unique_ptr hdr(sam_hdr_read(htsFile_.get())); + header_ = BamHeaderMemory::FromRawData(hdr.get()); + } + + std::string filename_; + std::unique_ptr htsFile_; + BamHeader header_; +}; + +BamReader::BamReader() : internal::IQuery(), d_{std::make_unique("-")} {} + +BamReader::BamReader(std::string fn) + : internal::IQuery(), d_{std::make_unique(std::move(fn))} +{ +} + +BamReader::BamReader(BamFile bamFile) : BamReader(bamFile.Filename()) {} + +BamReader::~BamReader() = default; + +BGZF* BamReader::Bgzf() const { return d_->htsFile_->fp.bgzf; } + +const std::string& BamReader::Filename() const { return d_->filename_; } + +const BamHeader& BamReader::Header() const { return d_->header_; } + +bool BamReader::GetNext(BamRecord& record) +{ + assert(BamRecordMemory::GetRawData(record).get()); + + const auto result = ReadRawData(Bgzf(), BamRecordMemory::GetRawData(record).get()); + + // success + if (result >= 0) { + BamRecordMemory::UpdateRecordTags(record); + record.header_ = d_->header_; + record.ResetCachedPositions(); + +#if PBBAM_AUTOVALIDATE + Validator::Validate(record); +#endif + return true; + } + + // EOF or end-of-data range (not an error) + else if (result == -1) + return false; + + // error corrupted file + else { + std::ostringstream msg; + msg << "BamReader: cannot read from corrupted file: " << Filename() << '\n' << " reason: "; + if (result == -2) + msg << "probably truncated"; + else if (result == -3) + msg << "could not read BAM record's' core data"; + else if (result == -4) + msg << "could not read BAM record's' variable-length data"; + else + msg << "unknown reason (status code = " << result << ") (" << Filename() << ')'; + throw std::runtime_error{msg.str()}; + } +} + +int BamReader::ReadRawData(BGZF* bgzf, bam1_t* b) { return bam_read1(bgzf, b); } + +void BamReader::VirtualSeek(int64_t virtualOffset) +{ + const auto result = bgzf_seek(Bgzf(), virtualOffset, SEEK_SET); + if (result != 0) throw std::runtime_error{"Failed to seek in BAM file"}; +} + +int64_t BamReader::VirtualTell() const { return bgzf_tell(Bgzf()); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamRecord.cpp b/src/BamRecord.cpp new file mode 100644 index 0000000..c53445c --- /dev/null +++ b/src/BamRecord.cpp @@ -0,0 +1,2006 @@ +// File Description +/// \file BamRecord.cpp +/// \brief Implements the BamRecord class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamRecord.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "BamRecordTags.h" +#include "MemoryUtils.h" +#include "Pulse2BaseCache.h" +#include "SequenceUtils.h" +#include "pbbam/StringUtilities.h" +#include "pbbam/ZmwTypeMap.h" +#include "pbbam/virtual/VirtualRegionTypeMap.h" + +namespace PacBio { +namespace BAM { +namespace { + +// record type names +const std::string recordTypeName_ZMW{"ZMW"}; +const std::string recordTypeName_Polymerase{"POLYMERASE"}; +const std::string recordTypeName_HqRegion{"HQREGION"}; +const std::string recordTypeName_Subread{"SUBREAD"}; +const std::string recordTypeName_CCS{"CCS"}; +const std::string recordTypeName_Scrap{"SCRAP"}; +const std::string recordTypeName_Transcript{"TRANSCRIPT"}; +const std::string recordTypeName_Unknown{"UNKNOWN"}; + +int32_t HoleNumberFromName(const std::string& fullName) +{ + const auto mainTokens = Split(fullName, '/'); + if (mainTokens.at(0) == "transcript") { + if (mainTokens.size() != 2) + throw std::runtime_error{"BamRecord: malformed transcript record name: " + fullName}; + return std::stoi(mainTokens.at(1)); + } else { + if (mainTokens.size() != 3) + throw std::runtime_error{"BamRecord: malformed record name: " + fullName}; + return std::stoi(mainTokens.at(1)); + } +} + +Position QueryEndFromName(const std::string& fullName) +{ + const auto mainTokens = Split(fullName, '/'); + if (mainTokens.size() != 3) + throw std::runtime_error{"BamRecord: malformed record name: " + fullName}; + + const auto queryTokens = Split(mainTokens.at(2), '_'); + if (queryTokens.size() != 2) + throw std::runtime_error{"BamRecord: malformed record name: " + fullName}; + + return stoi(queryTokens.at(1)); +} + +Position QueryStartFromName(const std::string& fullName) +{ + const auto mainTokens = Split(fullName, '/'); + if (mainTokens.size() != 3) + throw std::runtime_error{"BamRecord: malformed record name: " + fullName}; + + const auto queryTokens = Split(mainTokens.at(2), '_'); + if (queryTokens.size() != 2) + throw std::runtime_error{"BamRecord: malformed record name: " + fullName}; + + return stoi(queryTokens.at(0)); +} + +std::string Label(const BamRecordTag tag) { return BamRecordTags::LabelFor(tag); } + +BamRecordImpl* CreateOrEdit(const BamRecordTag tag, const Tag& value, BamRecordImpl* impl) +{ + if (impl->HasTag(tag)) + impl->EditTag(tag, value); + else + impl->AddTag(tag, value); + return impl; +} + +std::pair AlignedOffsets(const BamRecord& record, const int seqLength) +{ + int32_t startOffset = 0; + int32_t endOffset = seqLength; + + const auto b = BamRecordMemory::GetRawData(record); + uint32_t* cigarData = bam_get_cigar(b.get()); + const size_t numCigarOps = b->core.n_cigar; + if (numCigarOps > 0) { + + // start offset + for (size_t i = 0; i < numCigarOps; ++i) { + const auto type = static_cast(bam_cigar_op(cigarData[i])); + if (type == CigarOperationType::HARD_CLIP) { + if (startOffset != 0 && startOffset != seqLength) { + startOffset = -1; + break; + } + } else if (type == CigarOperationType::SOFT_CLIP) + startOffset += bam_cigar_oplen(cigarData[i]); + else + break; + } + + // end offset + for (int i = numCigarOps - 1; i >= 0; --i) { + const auto type = static_cast(bam_cigar_op(cigarData[i])); + if (type == CigarOperationType::HARD_CLIP) { + if (endOffset != 0 && endOffset != seqLength) { + endOffset = -1; + break; + } + } else if (type == CigarOperationType::SOFT_CLIP) + endOffset -= bam_cigar_oplen(cigarData[i]); + else + break; + } + + if (endOffset == 0) endOffset = seqLength; + } + return {startOffset, endOffset}; +} + +template +OutputIt Move_N(InputIt first, Size count, OutputIt result) +{ + return std::move(first, first + count, result); +} + +template +T ClipSeqQV(const T& input, const size_t pos, const size_t len) +{ + if (input.empty()) return {}; + return T{input.cbegin() + pos, input.cbegin() + pos + len}; +} + +template +T ClipPulse(const T& input, PacBio::BAM::Pulse2BaseCache* p2bCache, const size_t pos, + const size_t len) +{ + assert(p2bCache); + if (input.empty()) return {}; + + // find start + size_t start = p2bCache->FindFirst(); + size_t basesSeen = 0; + while (basesSeen < pos) { + start = p2bCache->FindNext(start); + ++basesSeen; + } + + // find end + size_t end = start; + size_t seen = 1; + while (seen < len) { + end = p2bCache->FindNext(end); + ++seen; + } + + // return clipped + return {input.cbegin() + start, input.cbegin() + end + 1}; +} + +template +void ClipAndGapify(const BamRecordImpl& impl, const bool aligned, const bool exciseSoftClips, + F* seq, N paddingNullValue, N deletionNullValue) +{ + assert(seq); + + const bool clipOrGapRequested = aligned || exciseSoftClips; + if (impl.IsMapped() && clipOrGapRequested) { + // determine final container length + auto incrementsOutputLength = [](const CigarOperationType type, const bool isAligned, + const bool exciseSoftClipsFromAln) { + if (type == CigarOperationType::HARD_CLIP || + type == CigarOperationType::REFERENCE_SKIP) { + return false; + } else if (type == CigarOperationType::SOFT_CLIP && exciseSoftClipsFromAln) { + return false; + } else if (!isAligned && (type == CigarOperationType::DELETION || + type == CigarOperationType::PADDING)) { + return false; + } else + return true; + }; + + size_t outputLength = 0; + const auto cigar = impl.CigarData(); + for (const CigarOperation& op : cigar) { + if (incrementsOutputLength(op.Type(), aligned, exciseSoftClips)) + outputLength += op.Length(); + } + + // move original data to temp, prep output container size + F originalSeq = std::move(*seq); + seq->resize(outputLength); + + // apply CIGAR ops + size_t srcIndex = 0; + size_t dstIndex = 0; + for (const CigarOperation& op : cigar) { + const auto opType = op.Type(); + const auto opLength = op.Length(); + + // nothing to do for hard-clipped & ref-skipped positions + if (opType == CigarOperationType::HARD_CLIP || + opType == CigarOperationType::REFERENCE_SKIP) { + continue; + } + + // maybe skip soft-clipped positions + else if (opType == CigarOperationType::SOFT_CLIP) { + if (exciseSoftClips) + srcIndex += opLength; + else { + Move_N(originalSeq.begin() + srcIndex, opLength, seq->begin() + dstIndex); + srcIndex += opLength; + dstIndex += opLength; + } + } + + // maybe add deletion/padding values + // either way, srcIndex is not incremented + else if (opType == CigarOperationType::DELETION) { + if (aligned) { + for (size_t i = 0; i < opLength; ++i) { + (*seq)[dstIndex] = deletionNullValue; + ++dstIndex; + } + } + } else if (opType == CigarOperationType::PADDING) { + if (aligned) { + for (size_t i = 0; i < opLength; ++i) { + (*seq)[dstIndex] = paddingNullValue; + ++dstIndex; + } + } + } + + // all other CIGAR ops + else { + Move_N(originalSeq.begin() + srcIndex, opLength, seq->begin() + dstIndex); + srcIndex += opLength; + dstIndex += opLength; + } + } + } +} + +void ClipAndGapifyBases(const BamRecordImpl& impl, const bool aligned, const bool exciseSoftClips, + std::string* seq) +{ + ClipAndGapify(impl, aligned, exciseSoftClips, seq, '*', '-'); +} + +void ClipAndGapifyFrames(const BamRecordImpl& impl, const bool aligned, const bool exciseSoftClips, + Frames* frames) +{ + assert(frames); + std::vector data{std::move(frames->Data())}; + ClipAndGapify, uint16_t>(impl, aligned, exciseSoftClips, &data, 0, 0); + frames->Data(data); +} + +void ClipAndGapifyPhotons(const BamRecordImpl& impl, const bool aligned, const bool exciseSoftClips, + std::vector* data) +{ + ClipAndGapify, float>(impl, aligned, exciseSoftClips, data, 0.0, 0.0); +} + +void ClipAndGapifyQualities(const BamRecordImpl& impl, const bool aligned, + const bool exciseSoftClips, QualityValues* quals) +{ + ClipAndGapify(impl, aligned, exciseSoftClips, quals, + QualityValue(0), QualityValue(0)); +} + +void ClipAndGapifyUInts(const BamRecordImpl& impl, const bool aligned, const bool exciseSoftClips, + std::vector* data) +{ + ClipAndGapify, uint32_t>(impl, aligned, exciseSoftClips, data, 0, 0); +} + +void ClipAndGapifyUInt8s(const BamRecordImpl& impl, const bool aligned, const bool exciseSoftClips, + std::vector* data) +{ + ClipAndGapify, uint8_t>(impl, aligned, exciseSoftClips, data, 0, 0); +} + +RecordType NameToType(const std::string& name) +{ + if (name == recordTypeName_Subread) return RecordType::SUBREAD; + if (name == recordTypeName_ZMW || name == recordTypeName_Polymerase) return RecordType::ZMW; + if (name == recordTypeName_HqRegion) return RecordType::HQREGION; + if (name == recordTypeName_CCS) return RecordType::CCS; + if (name == recordTypeName_Scrap) return RecordType::SCRAP; + if (name == recordTypeName_Transcript) return RecordType::TRANSCRIPT; + return RecordType::UNKNOWN; +} + +void OrientBasesAsRequested(std::string* bases, Orientation current, Orientation requested, + bool isReverseStrand, bool isPulse) +{ + assert(bases); + if (current != requested && isReverseStrand) { + if (isPulse) + ReverseComplementCaseSens(*bases); + else + ReverseComplement(*bases); + } +} + +template +void OrientTagDataAsRequested(Container* data, Orientation current, Orientation requested, + bool isReverseStrand) +{ + assert(data); + if (current != requested && isReverseStrand) std::reverse(data->begin(), data->end()); +} + +} // namespace + +const float BamRecord::photonFactor = 10.0; + +BamRecord::BamRecord() + : alignedStart_{PacBio::BAM::UnmappedPosition}, alignedEnd_{PacBio::BAM::UnmappedPosition} +{ +} + +BamRecord::BamRecord(BamHeader header) + : header_{std::move(header)} + , alignedStart_{PacBio::BAM::UnmappedPosition} + , alignedEnd_{PacBio::BAM::UnmappedPosition} +{ +} + +BamRecord::BamRecord(BamRecordImpl impl) + : impl_{std::move(impl)} + , alignedStart_{PacBio::BAM::UnmappedPosition} + , alignedEnd_{PacBio::BAM::UnmappedPosition} +{ +} + +BamRecord::BamRecord(const BamRecord& other) + : impl_{other.impl_} + , header_{other.header_} + , alignedStart_{other.alignedStart_} + , alignedEnd_{other.alignedEnd_} +{ +} + +BamRecord::BamRecord(BamRecord&&) noexcept = default; + +BamRecord& BamRecord::operator=(const BamRecord& other) +{ + if (this != &other) { + impl_ = other.impl_; + header_ = other.header_; + alignedStart_ = other.alignedStart_; + alignedEnd_ = other.alignedEnd_; + p2bCache_.reset(); // just reset, for now at least + } + return *this; +} + +BamRecord& BamRecord::operator=(BamRecord&&) noexcept = default; + +BamRecord::~BamRecord() = default; + +Position BamRecord::AlignedEnd() const +{ + if (alignedEnd_ == PacBio::BAM::UnmappedPosition) CalculateAlignedPositions(); + return alignedEnd_; +} + +Position BamRecord::AlignedStart() const +{ + if (alignedStart_ == PacBio::BAM::UnmappedPosition) CalculateAlignedPositions(); + return alignedStart_; +} + +Strand BamRecord::AlignedStrand() const +{ + return impl_.IsReverseStrand() ? Strand::REVERSE : Strand::FORWARD; +} + +QualityValues BamRecord::AltLabelQV(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchQualities(BamRecordTag::ALT_LABEL_QV, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::AltLabelQV(const QualityValues& altLabelQVs) +{ + CreateOrEdit(BamRecordTag::ALT_LABEL_QV, altLabelQVs.Fastq(), &impl_); + return *this; +} + +std::string BamRecord::AltLabelTag(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchBases(BamRecordTag::ALT_LABEL_TAG, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::AltLabelTag(const std::string& tags) +{ + CreateOrEdit(BamRecordTag::ALT_LABEL_TAG, tags, &impl_); + return *this; +} + +int16_t BamRecord::BarcodeForward() const { return Barcodes().first; } + +int16_t BamRecord::BarcodeReverse() const { return Barcodes().second; } + +uint8_t BamRecord::BarcodeQuality() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::BARCODE_QUALITY); + const auto bq = impl_.TagValue(tagName); + if (bq.IsNull()) + return 0; // ?? "missing" value for tags ?? should we consider boost::optional for these kind of guys ?? + return bq.ToUInt8(); +} + +BamRecord& BamRecord::BarcodeQuality(const uint8_t quality) +{ + CreateOrEdit(BamRecordTag::BARCODE_QUALITY, quality, &impl_); + return *this; +} + +std::pair BamRecord::Barcodes() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::BARCODES); + const Tag bc = impl_.TagValue(tagName); + if (bc.IsNull()) + throw std::runtime_error{"BamRecord: barcode tag (bc) was requested but is missing"}; + + // NOTE: barcodes are still stored, per the spec, as uint16, even though + // we're now using them as int16_t in the API (bug 31511) + // + if (!bc.IsUInt16Array()) + throw std::runtime_error{ + "BamRecord: barcode tag (bc) is malformed: should be a uint16_t array of size==2."}; + const auto bcArray = bc.ToUInt16Array(); + if (bcArray.size() != 2) + throw std::runtime_error{ + "BamRecord: barcode tag (bc) is malformed: should be a uint16_t array of size==2."}; + + return {boost::numeric_cast(bcArray[0]), boost::numeric_cast(bcArray[1])}; +} + +BamRecord& BamRecord::Barcodes(const std::pair& barcodeIds) +{ + const std::vector data{boost::numeric_cast(barcodeIds.first), + boost::numeric_cast(barcodeIds.second)}; + CreateOrEdit(BamRecordTag::BARCODES, data, &impl_); + return *this; +} + +void BamRecord::CalculateAlignedPositions() const +{ + // reset + ResetCachedPositions(); + + // skip if unmapped, or has no queryStart/End + if (!impl_.IsMapped()) return; + + // get the query start/end + const auto seqLength = static_cast(impl_.SequenceLength()); + const bool isCcsOrTranscript = IsCcsOrTranscript(Type()); + const Position qStart = isCcsOrTranscript ? 0 : QueryStart(); + const Position qEnd = isCcsOrTranscript ? seqLength : QueryEnd(); + + if (qStart == PacBio::BAM::UnmappedPosition || qEnd == PacBio::BAM::UnmappedPosition) return; + + // determine clipped end ranges + const auto alignedOffsets = AlignedOffsets(*this, seqLength); + const auto startOffset = alignedOffsets.first; + const auto endOffset = alignedOffsets.second; + if (endOffset == -1 || startOffset == -1) return; // TODO: handle error more?? + + // store aligned positions (polymerase read coordinates) + if (impl_.IsReverseStrand()) { + alignedStart_ = qStart + (seqLength - endOffset); + alignedEnd_ = qEnd - startOffset; + } else { + alignedStart_ = qStart + startOffset; + alignedEnd_ = qEnd - (seqLength - endOffset); + } +} + +void BamRecord::CalculatePulse2BaseCache() const +{ + // skip already calculated + if (p2bCache_) return; + + // else try to calculate p2b cache. + if (!HasPulseCall()) + throw std::runtime_error{ + "BamRecord: cannot calculate pulse2base mapping without 'pc' tag."}; + const auto pulseCalls = + FetchBases(BamRecordTag::PULSE_CALL, Orientation::NATIVE, false, false, PulseBehavior::ALL); + p2bCache_ = std::make_unique(pulseCalls); +} + +Cigar BamRecord::CigarData(bool exciseAllClips) const +{ + auto isClippingOp = [](const CigarOperation& op) { + const auto type = op.Type(); + return type == CigarOperationType::SOFT_CLIP || type == CigarOperationType::HARD_CLIP; + }; + + auto cigar = impl_.CigarData(); + if (exciseAllClips) { + cigar.erase(std::remove_if(cigar.begin(), cigar.end(), isClippingOp), cigar.end()); + } + return cigar; +} + +BamRecord& BamRecord::Clip(const ClipType clipType, const Position start, const Position end, + const bool exciseFlankingInserts) +{ + switch (clipType) { + case ClipType::CLIP_NONE: + return *this; + case ClipType::CLIP_TO_QUERY: + // exciseFlankingInserts ignored, just clipping to query coordinates + return ClipToQuery(start, end); + case ClipType::CLIP_TO_REFERENCE: + return ClipToReference(start, end, exciseFlankingInserts); + default: + throw std::runtime_error{"BamRecord: unsupported clip type requested"}; + } +} + +BamRecord BamRecord::Clipped(const BamRecord& input, const ClipType clipType, + const PacBio::BAM::Position start, const PacBio::BAM::Position end, + const bool exciseFlankingInserts) +{ + return input.Clipped(clipType, start, end, exciseFlankingInserts); +} + +BamRecord BamRecord::Clipped(const ClipType clipType, const PacBio::BAM::Position start, + const PacBio::BAM::Position end, + const bool exciseFlankingInserts) const +{ + BamRecord result(*this); + result.Clip(clipType, start, end, exciseFlankingInserts); + return result; +} + +void BamRecord::ClipTags(const size_t clipFrom, const size_t clipLength) +{ + const auto ipdCodec = ReadGroup().IpdCodec(); + const auto pwCodec = ReadGroup().PulseWidthCodec(); + + // update BAM tags + TagCollection tags = impl_.Tags(); + if (HasDeletionQV()) + tags[Label(BamRecordTag::DELETION_QV)] = + ClipSeqQV(DeletionQV(Orientation::NATIVE), clipFrom, clipLength).Fastq(); + if (HasInsertionQV()) + tags[Label(BamRecordTag::INSERTION_QV)] = + ClipSeqQV(InsertionQV(Orientation::NATIVE), clipFrom, clipLength).Fastq(); + if (HasMergeQV()) + tags[Label(BamRecordTag::MERGE_QV)] = + ClipSeqQV(MergeQV(Orientation::NATIVE), clipFrom, clipLength).Fastq(); + if (HasSubstitutionQV()) + tags[Label(BamRecordTag::SUBSTITUTION_QV)] = + ClipSeqQV(SubstitutionQV(Orientation::NATIVE), clipFrom, clipLength).Fastq(); + if (HasIPD()) { + if (ipdCodec == FrameCodec::RAW) + tags[Label(BamRecordTag::IPD)] = + ClipSeqQV(IPD(Orientation::NATIVE).Data(), clipFrom, clipLength); + else if (ipdCodec == FrameCodec::V1) + tags[Label(BamRecordTag::IPD)] = + ClipSeqQV(IPD(Orientation::NATIVE).Encode(), clipFrom, clipLength); + } + if (HasPulseWidth()) { + if (pwCodec == FrameCodec::RAW) + tags[Label(BamRecordTag::PULSE_WIDTH)] = + ClipSeqQV(PulseWidth(Orientation::NATIVE).Data(), clipFrom, clipLength); + else if (pwCodec == FrameCodec::V1) + tags[Label(BamRecordTag::PULSE_WIDTH)] = + ClipSeqQV(PulseWidth(Orientation::NATIVE).Encode(), clipFrom, clipLength); + } + if (HasDeletionTag()) + tags[Label(BamRecordTag::DELETION_TAG)] = + ClipSeqQV(DeletionTag(Orientation::NATIVE), clipFrom, clipLength); + if (HasSubstitutionTag()) + tags[Label(BamRecordTag::SUBSTITUTION_TAG)] = + ClipSeqQV(SubstitutionTag(Orientation::NATIVE), clipFrom, clipLength); + + // internal BAM tags + if (HasPulseCall()) { + + // ensure p2bCache initialized + CalculatePulse2BaseCache(); + Pulse2BaseCache* p2bCache = p2bCache_.get(); + + if (HasAltLabelQV()) + tags[Label(BamRecordTag::ALT_LABEL_QV)] = + ClipPulse(AltLabelQV(Orientation::NATIVE), p2bCache, clipFrom, clipLength).Fastq(); + if (HasLabelQV()) + tags[Label(BamRecordTag::LABEL_QV)] = + ClipPulse(LabelQV(Orientation::NATIVE), p2bCache, clipFrom, clipLength).Fastq(); + if (HasPulseMergeQV()) + tags[Label(BamRecordTag::PULSE_MERGE_QV)] = + ClipPulse(PulseMergeQV(Orientation::NATIVE), p2bCache, clipFrom, clipLength) + .Fastq(); + if (HasAltLabelTag()) + tags[Label(BamRecordTag::ALT_LABEL_TAG)] = + ClipPulse(AltLabelTag(Orientation::NATIVE), p2bCache, clipFrom, clipLength); + if (HasPulseCall()) + tags[Label(BamRecordTag::PULSE_CALL)] = + ClipPulse(PulseCall(Orientation::NATIVE), p2bCache, clipFrom, clipLength); + if (HasPkmean()) + tags[Label(BamRecordTag::PKMEAN)] = EncodePhotons( + ClipPulse(Pkmean(Orientation::NATIVE), p2bCache, clipFrom, clipLength)); + if (HasPkmid()) + tags[Label(BamRecordTag::PKMID)] = EncodePhotons( + ClipPulse(Pkmid(Orientation::NATIVE), p2bCache, clipFrom, clipLength)); + if (HasPkmean2()) + tags[Label(BamRecordTag::PKMEAN_2)] = EncodePhotons( + ClipPulse(Pkmean2(Orientation::NATIVE), p2bCache, clipFrom, clipLength)); + if (HasPkmid2()) + tags[Label(BamRecordTag::PKMID_2)] = EncodePhotons( + ClipPulse(Pkmid2(Orientation::NATIVE), p2bCache, clipFrom, clipLength)); + if (HasPrePulseFrames()) + tags[Label(BamRecordTag::PRE_PULSE_FRAMES)] = ClipPulse( + PrePulseFrames(Orientation::NATIVE).Data(), p2bCache, clipFrom, clipLength); + if (HasPulseCallWidth()) + tags[Label(BamRecordTag::PULSE_CALL_WIDTH)] = ClipPulse( + PulseCallWidth(Orientation::NATIVE).Data(), p2bCache, clipFrom, clipLength); + if (HasStartFrame()) + tags[Label(BamRecordTag::START_FRAME)] = + ClipPulse(StartFrame(Orientation::NATIVE), p2bCache, clipFrom, clipLength); + } + + impl_.Tags(tags); +} + +void BamRecord::ClipFields(const size_t clipFrom, const size_t clipLength) +{ + const bool isForwardStrand = (AlignedStrand() == Strand::FORWARD); + + // clip seq, quals + std::string sequence{ClipSeqQV(Sequence(Orientation::NATIVE), clipFrom, clipLength)}; + QualityValues qualities{ClipSeqQV(Qualities(Orientation::NATIVE), clipFrom, clipLength)}; + if (!isForwardStrand) { + ReverseComplement(sequence); + Reverse(qualities); + } + impl_.SetSequenceAndQualities(sequence, qualities.Fastq()); + + ClipTags(clipFrom, clipLength); +} + +BamRecord& BamRecord::ClipToQuery(const Position start, const Position end) +{ + // cache original coords, skip out if clip not needed + const size_t seqLength = impl_.SequenceLength(); + const bool isCcsOrTranscript = IsCcsOrTranscript(Type()); + const Position origQStart = isCcsOrTranscript ? 0 : QueryStart(); + const Position origQEnd = isCcsOrTranscript ? seqLength : QueryEnd(); + if (start <= origQStart && end >= origQEnd) return *this; + + // calculate clipping + Data::ClipToQueryConfig clipConfig{ + impl_.SequenceLength(), origQStart, origQEnd, start, end, + impl_.Position(), AlignedStrand(), impl_.CigarData(), impl_.IsMapped()}; + auto result = Data::ClipToQuery(clipConfig); + + // update alignment info + if (IsMapped()) { + impl_.CigarData(std::move(result.cigar_)); + impl_.Position(result.refPos_); + } + + // clip SEQ, QUAL, tags + const auto clipFrom = result.clipOffset_; + const auto clipLength = (end - start); + ClipFields(clipFrom, clipLength); + + // update query start/end + // TODO: update name to reflect new QS/QE ??? + CreateOrEdit(BamRecordTag::QUERY_START, start, &impl_); + CreateOrEdit(BamRecordTag::QUERY_END, end, &impl_); + + // reset any cached aligned start/end + ResetCachedPositions(); + return *this; +} + +BamRecord& BamRecord::ClipToReference(const Position start, const Position end, + const bool exciseFlankingInserts) +{ + // skip if not mapped, clipping to reference doesn't make sense + // or should we even consider throwing here? + if (!IsMapped()) return *this; + + // cache original coords + const int seqLength = static_cast(impl_.SequenceLength()); + const bool isCcsOrTranscript = IsCcsOrTranscript(Type()); + const Position origQStart = isCcsOrTranscript ? 0 : QueryStart(); + const Position origQEnd = isCcsOrTranscript ? seqLength : QueryEnd(); + const Position origTStart = ReferenceStart(); + const Position origTEnd = ReferenceEnd(); + + // skip if already within requested clip range + if (start <= origTStart && end >= origTEnd) return *this; + assert(AlignedStart() >= origQStart); + assert(AlignedEnd() <= origQEnd); + + // calculate clipping + Data::ClipToReferenceConfig clipConfig{ + Data::ClipToQueryConfig{impl_.SequenceLength(), origQStart, origQEnd, start, end, + impl_.Position(), AlignedStrand(), impl_.CigarData(), + impl_.IsMapped()}, + ReferenceEnd(), start, end, exciseFlankingInserts}; + auto result = Data::ClipToReference(clipConfig); + + // update CIGAR and position + impl_.CigarData(std::move(result.cigar_)); + impl_.Position(result.refPos_); + + // clip SEQ, QUAL, tags + const Position qStart = result.qStart_; + const Position qEnd = result.qEnd_; + const size_t clipFrom = result.clipOffset_; + const size_t clipLength = qEnd - qStart; + ClipFields(clipFrom, clipLength); + + // update query start/end + CreateOrEdit(BamRecordTag::QUERY_START, qStart, &impl_); + CreateOrEdit(BamRecordTag::QUERY_END, qEnd, &impl_); + + // reset any cached aligned start/end + ResetCachedPositions(); + return *this; +} + +QualityValues BamRecord::DeletionQV(Orientation orientation, bool aligned, + bool exciseSoftClips) const +{ + return FetchQualities(BamRecordTag::DELETION_QV, orientation, aligned, exciseSoftClips); +} + +BamRecord& BamRecord::DeletionQV(const QualityValues& deletionQVs) +{ + CreateOrEdit(BamRecordTag::DELETION_QV, deletionQVs.Fastq(), &impl_); + return *this; +} + +std::string BamRecord::DeletionTag(Orientation orientation, bool aligned, + bool exciseSoftClips) const +{ + return FetchBases(BamRecordTag::DELETION_TAG, orientation, aligned, exciseSoftClips); +} + +BamRecord& BamRecord::DeletionTag(const std::string& tags) +{ + CreateOrEdit(BamRecordTag::DELETION_TAG, tags, &impl_); + return *this; +} + +std::vector BamRecord::EncodePhotons(const std::vector& data) +{ + std::vector encoded; + encoded.reserve(data.size()); + for (const auto& d : data) + encoded.emplace_back(d * photonFactor); + return encoded; +} + +std::string BamRecord::FetchBasesRaw(const BamRecordTag tag) const +{ + const Tag seqTag = impl_.TagValue(tag); + return seqTag.ToString(); +} + +std::string BamRecord::FetchBases(const BamRecordTag tag, const Orientation orientation, + const bool aligned, const bool exciseSoftClips, + const PulseBehavior pulseBehavior) const +{ + const bool isBamSeq = (tag == BamRecordTag::SEQ); + const bool isPulse = BamRecordTags::IsPulse(tag); + + // fetch raw + std::string bases; + Orientation current; + if (isBamSeq) { // SEQ stored in genomic orientation + bases = impl_.Sequence(); + current = Orientation::GENOMIC; + } else { // all tags stored in native orientation + bases = FetchBasesRaw(tag); + current = Orientation::NATIVE; + } + + // maybe strip 'squashed' pulse loci + if (isPulse && pulseBehavior == PulseBehavior::BASECALLS_ONLY) { + CalculatePulse2BaseCache(); + bases = p2bCache_->RemoveSquashedPulses(bases); + } + + // if we need to touch CIGAR + if (aligned || exciseSoftClips) { + + if (isPulse && pulseBehavior != PulseBehavior::BASECALLS_ONLY) + throw std::runtime_error{ + "BamRecord: cannot return data at all pulses when gapping and/or soft-clipping are " + "requested. " + "Use PulseBehavior::BASECALLS_ONLY instead."}; + + // force into genomic orientation + OrientBasesAsRequested(&bases, current, Orientation::GENOMIC, impl_.IsReverseStrand(), + isPulse); + current = Orientation::GENOMIC; + + // clip & gapify as requested + ClipAndGapifyBases(impl_, aligned, exciseSoftClips, &bases); + } + + // return in the orientation requested + OrientBasesAsRequested(&bases, current, orientation, impl_.IsReverseStrand(), isPulse); + return bases; +} + +Frames BamRecord::FetchFramesRaw(const BamRecordTag tag) const +{ + const Tag frameTag = impl_.TagValue(tag); + if (frameTag.IsNull()) return {}; // throw ? + + // lossy frame codes + if (frameTag.IsUInt8Array()) { + const auto codes = frameTag.ToUInt8Array(); + return Frames::Decode(codes); + } + + // lossless frame data + else { + assert(frameTag.IsUInt16Array()); + return Frames{frameTag.ToUInt16Array()}; + } +} + +Frames BamRecord::FetchFrames(const BamRecordTag tag, const Orientation orientation, + const bool aligned, const bool exciseSoftClips, + const PulseBehavior pulseBehavior) const +{ + const bool isPulse = BamRecordTags::IsPulse(tag); + + // fetch raw + Frames frames = FetchFramesRaw(tag); + Orientation current = Orientation::NATIVE; + + // maybe strip 'squashed' pulse loci + if (isPulse && pulseBehavior == PulseBehavior::BASECALLS_ONLY) { + CalculatePulse2BaseCache(); + frames.DataRaw() = p2bCache_->RemoveSquashedPulses(frames.Data()); + } + + // if we need to touch the CIGAR + if (aligned || exciseSoftClips) { + + if (isPulse && pulseBehavior != PulseBehavior::BASECALLS_ONLY) + throw std::runtime_error{ + "BamRecord: cannot return data at all pulses when gapping and/or soft-clipping are " + "requested. " + "Use PulseBehavior::BASECALLS_ONLY instead."}; + + // force into genomic orientation + OrientTagDataAsRequested(&frames, current, Orientation::GENOMIC, impl_.IsReverseStrand()); + current = Orientation::GENOMIC; + + // clip & gapify as requested + ClipAndGapifyFrames(impl_, aligned, exciseSoftClips, &frames); + } + + // return in the orientation requested + OrientTagDataAsRequested(&frames, current, orientation, impl_.IsReverseStrand()); + return frames; +} + +std::vector BamRecord::FetchPhotonsRaw(const BamRecordTag tag) const +{ + const Tag frameTag = impl_.TagValue(tag); + if (frameTag.IsNull()) return {}; + if (!frameTag.IsUInt16Array()) + throw std::runtime_error{"BamRecord: photons are not a uint16_t array, tag " + + BamRecordTags::LabelFor(tag)}; + + const auto data = frameTag.ToUInt16Array(); + std::vector photons; + photons.reserve(data.size()); + for (const auto& d : data) + photons.emplace_back(d / photonFactor); + return photons; +} + +std::vector BamRecord::FetchPhotons(const BamRecordTag tag, const Orientation orientation, + const bool aligned, const bool exciseSoftClips, + const PulseBehavior pulseBehavior) const +{ + const bool isPulse = BamRecordTags::IsPulse(tag); + + // fetch raw + auto data = FetchPhotonsRaw(tag); + Orientation current = Orientation::NATIVE; + + if (isPulse && pulseBehavior == PulseBehavior::BASECALLS_ONLY) { + // strip 'squashed' pulse loci + CalculatePulse2BaseCache(); + data = p2bCache_->RemoveSquashedPulses(data); + } + + if (aligned || exciseSoftClips) { + + if (isPulse && pulseBehavior != PulseBehavior::BASECALLS_ONLY) + throw std::runtime_error{ + "BamRecord: cannot return data at all pulses when gapping and/or soft-clipping are " + "requested. " + "Use PulseBehavior::BASECALLS_ONLY instead."}; + + // force into genomic orientation + OrientTagDataAsRequested(&data, current, Orientation::GENOMIC, impl_.IsReverseStrand()); + current = Orientation::GENOMIC; + + // clip & gapify as requested + ClipAndGapifyPhotons(impl_, aligned, exciseSoftClips, &data); + } + + // return in the orientation requested + OrientTagDataAsRequested(&data, current, orientation, impl_.IsReverseStrand()); + return data; +} + +QualityValues BamRecord::FetchQualitiesRaw(const BamRecordTag tag) const +{ + const Tag qvsTag = impl_.TagValue(tag); + return QualityValues::FromFastq(qvsTag.ToString()); +} + +QualityValues BamRecord::FetchQualities(const BamRecordTag tag, const Orientation orientation, + const bool aligned, const bool exciseSoftClips, + const PulseBehavior pulseBehavior) const +{ + // requested data info + const bool isBamQual = (tag == BamRecordTag::QUAL); + const bool isPulse = BamRecordTags::IsPulse(tag); + + // fetch raw + QualityValues quals; + Orientation current; + if (isBamQual) { // QUAL stored in genomic orientation + quals = impl_.Qualities(); + current = Orientation::GENOMIC; + } else { // all tags stored in native orientation + quals = FetchQualitiesRaw(tag); + current = Orientation::NATIVE; + } + + if (isPulse && pulseBehavior == PulseBehavior::BASECALLS_ONLY) { + // strip 'squashed' pulse loci + CalculatePulse2BaseCache(); + quals = p2bCache_->RemoveSquashedPulses(quals); + } + + // if we need to touch CIGAR + if (aligned || exciseSoftClips) { + + if (isPulse && pulseBehavior != PulseBehavior::BASECALLS_ONLY) + throw std::runtime_error{ + "BamRecord: cannot return data at all pulses when gapping and/or soft-clipping are " + "requested. " + "Use PulseBehavior::BASECALLS_ONLY instead."}; + + // force into genomic orientation + OrientTagDataAsRequested(&quals, current, Orientation::GENOMIC, impl_.IsReverseStrand()); + current = Orientation::GENOMIC; + + // clip & gapify as requested + ClipAndGapifyQualities(impl_, aligned, exciseSoftClips, &quals); + } + + // return in the orientation requested + OrientTagDataAsRequested(&quals, current, orientation, impl_.IsReverseStrand()); + return quals; +} + +std::vector BamRecord::FetchUInt32sRaw(const BamRecordTag tag) const +{ + // fetch tag data + const Tag frameTag = impl_.TagValue(tag); + if (frameTag.IsNull()) return {}; + if (!frameTag.IsUInt32Array()) + throw std::runtime_error{"BamRecord: tag data are not a uint32_t array, tag " + + BamRecordTags::LabelFor(tag)}; + return frameTag.ToUInt32Array(); +} + +std::vector BamRecord::FetchUInt32s(const BamRecordTag tag, const Orientation orientation, + const bool aligned, const bool exciseSoftClips, + const PulseBehavior pulseBehavior) const +{ + const bool isPulse = BamRecordTags::IsPulse(tag); + + // fetch raw + auto arr = FetchUInt32sRaw(tag); + Orientation current = Orientation::NATIVE; + + if (isPulse && pulseBehavior == PulseBehavior::BASECALLS_ONLY) { + // strip 'squashed' pulse loci + CalculatePulse2BaseCache(); + arr = p2bCache_->RemoveSquashedPulses(arr); + } + + if (aligned || exciseSoftClips) { + + if (isPulse && pulseBehavior != PulseBehavior::BASECALLS_ONLY) + throw std::runtime_error{ + "BamRecord: cannot return data at all pulses when gapping and/or soft-clipping are " + "requested. " + "Use PulseBehavior::BASECALLS_ONLY instead."}; + + // force into genomic orientation + OrientTagDataAsRequested(&arr, current, Orientation::GENOMIC, impl_.IsReverseStrand()); + current = Orientation::GENOMIC; + + // clip & gapify as requested + ClipAndGapifyUInts(impl_, aligned, exciseSoftClips, &arr); + } + + // return in the orientation requested + OrientTagDataAsRequested(&arr, current, orientation, impl_.IsReverseStrand()); + return arr; +} + +std::vector BamRecord::FetchUInt8sRaw(const BamRecordTag tag) const +{ + // fetch tag data + const Tag frameTag = impl_.TagValue(tag); + if (frameTag.IsNull()) return {}; + if (!frameTag.IsUInt8Array()) + throw std::runtime_error{"BamRecord: tag data are not a uint8_t array, tag " + + BamRecordTags::LabelFor(tag)}; + return frameTag.ToUInt8Array(); +} + +std::vector BamRecord::FetchUInt8s(const BamRecordTag tag, const Orientation orientation, + const bool aligned, const bool exciseSoftClips, + const PulseBehavior pulseBehavior) const +{ + const bool isPulse = BamRecordTags::IsPulse(tag); + + // fetch raw + auto arr = FetchUInt8sRaw(tag); + Orientation current = Orientation::NATIVE; + + if (isPulse && pulseBehavior == PulseBehavior::BASECALLS_ONLY) { + // strip 'squashed' pulse loci + CalculatePulse2BaseCache(); + arr = p2bCache_->RemoveSquashedPulses(arr); + } + + if (aligned || exciseSoftClips) { + + if (isPulse && pulseBehavior != PulseBehavior::BASECALLS_ONLY) + throw std::runtime_error{ + "BamRecord: cannot return data at all pulses when gapping and/or soft-clipping are " + "requested. " + "Use PulseBehavior::BASECALLS_ONLY instead."}; + + // force into genomic orientation + OrientTagDataAsRequested(&arr, current, Orientation::GENOMIC, impl_.IsReverseStrand()); + current = Orientation::GENOMIC; + + // clip & gapify as requested + ClipAndGapifyUInt8s(impl_, aligned, exciseSoftClips, &arr); + } + + // return in the orientation requested + OrientTagDataAsRequested(&arr, current, orientation, impl_.IsReverseStrand()); + return arr; +} + +std::string BamRecord::FullName() const { return impl_.Name(); } + +bool BamRecord::HasAltLabelQV() const { return impl_.HasTag(BamRecordTag::ALT_LABEL_QV); } + +bool BamRecord::HasAltLabelTag() const { return impl_.HasTag(BamRecordTag::ALT_LABEL_TAG); } + +bool BamRecord::HasBarcodes() const { return impl_.HasTag(BamRecordTag::BARCODES); } + +bool BamRecord::HasBarcodeQuality() const { return impl_.HasTag(BamRecordTag::BARCODE_QUALITY); } + +bool BamRecord::HasLabelQV() const { return impl_.HasTag(BamRecordTag::LABEL_QV); } + +bool BamRecord::HasDeletionQV() const { return impl_.HasTag(BamRecordTag::DELETION_QV); } + +bool BamRecord::HasDeletionTag() const { return impl_.HasTag(BamRecordTag::DELETION_TAG); } + +bool BamRecord::HasHoleNumber() const +{ + return impl_.HasTag(BamRecordTag::HOLE_NUMBER) && + !impl_.TagValue(BamRecordTag::HOLE_NUMBER).IsNull(); +} + +bool BamRecord::HasInsertionQV() const { return impl_.HasTag(BamRecordTag::INSERTION_QV); } + +bool BamRecord::HasNumPasses() const { return impl_.HasTag(BamRecordTag::NUM_PASSES); } + +bool BamRecord::HasPreBaseFrames() const { return HasIPD(); } + +bool BamRecord::HasIPD() const { return impl_.HasTag(BamRecordTag::IPD); } + +bool BamRecord::HasLocalContextFlags() const { return impl_.HasTag(BamRecordTag::CONTEXT_FLAGS); } + +bool BamRecord::HasMergeQV() const { return impl_.HasTag(BamRecordTag::MERGE_QV); } + +bool BamRecord::HasPulseMergeQV() const { return impl_.HasTag(BamRecordTag::PULSE_MERGE_QV); } + +bool BamRecord::HasPkmean() const { return impl_.HasTag(BamRecordTag::PKMEAN); } + +bool BamRecord::HasPkmean2() const { return impl_.HasTag(BamRecordTag::PKMEAN_2); } + +bool BamRecord::HasPkmid() const { return impl_.HasTag(BamRecordTag::PKMID); } + +bool BamRecord::HasPkmid2() const { return impl_.HasTag(BamRecordTag::PKMID_2); } + +bool BamRecord::HasPrePulseFrames() const { return impl_.HasTag(BamRecordTag::PRE_PULSE_FRAMES); } + +bool BamRecord::HasPulseCall() const +{ + return impl_.HasTag(BamRecordTag::PULSE_CALL) && + !impl_.TagValue(BamRecordTag::PULSE_CALL).IsNull(); +} + +bool BamRecord::HasPulseExclusion() const { return impl_.HasTag(BamRecordTag::PULSE_EXCLUSION); } + +bool BamRecord::HasPulseCallWidth() const { return impl_.HasTag(BamRecordTag::PULSE_CALL_WIDTH); } + +bool BamRecord::HasPulseWidth() const { return impl_.HasTag(BamRecordTag::PULSE_WIDTH); } + +bool BamRecord::HasQueryEnd() const { return impl_.HasTag(BamRecordTag::QUERY_END); } + +bool BamRecord::HasQueryEndFrameNumber() const +{ + return impl_.HasTag(BamRecordTag::QUERY_END_FRAME_NUMBER); +} + +bool BamRecord::HasQueryStart() const { return impl_.HasTag(BamRecordTag::QUERY_START); } + +bool BamRecord::HasQueryStartFrameNumber() const +{ + return impl_.HasTag(BamRecordTag::QUERY_START_FRAME_NUMBER); +} + +bool BamRecord::HasReadAccuracy() const +{ + return impl_.HasTag(BamRecordTag::READ_ACCURACY) && + !impl_.TagValue(BamRecordTag::READ_ACCURACY).IsNull(); +} + +bool BamRecord::HasScrapRegionType() const +{ + return impl_.HasTag(BamRecordTag::SCRAP_REGION_TYPE) && + !impl_.TagValue(BamRecordTag::SCRAP_REGION_TYPE).IsNull(); +} + +bool BamRecord::HasScrapZmwType() const +{ + return impl_.HasTag(BamRecordTag::SCRAP_ZMW_TYPE) && + !impl_.TagValue(BamRecordTag::SCRAP_ZMW_TYPE).IsNull(); +} + +bool BamRecord::HasStartFrame() const { return impl_.HasTag(BamRecordTag::START_FRAME); } + +bool BamRecord::HasSignalToNoise() const { return impl_.HasTag(BamRecordTag::SIGNAL_TO_NOISE); } + +bool BamRecord::HasSubstitutionQV() const { return impl_.HasTag(BamRecordTag::SUBSTITUTION_QV); } + +bool BamRecord::HasSubstitutionTag() const { return impl_.HasTag(BamRecordTag::SUBSTITUTION_TAG); } + +BamHeader BamRecord::Header() const { return header_; } + +int32_t BamRecord::HoleNumber() const +{ + const Tag holeNumber = impl_.TagValue(BamRecordTag::HOLE_NUMBER); + if (!holeNumber.IsNull()) return holeNumber.ToInt32(); + + // missing zm tag - try to pull from name + return HoleNumberFromName(FullName()); +} + +BamRecord& BamRecord::HoleNumber(const int32_t holeNumber) +{ + CreateOrEdit(BamRecordTag::HOLE_NUMBER, holeNumber, &impl_); + return *this; +} + +BamRecordImpl& BamRecord::Impl() { return impl_; } + +const BamRecordImpl& BamRecord::Impl() const { return impl_; } + +QualityValues BamRecord::InsertionQV(Orientation orientation, bool aligned, + bool exciseSoftClips) const +{ + return FetchQualities(BamRecordTag::INSERTION_QV, orientation, aligned, exciseSoftClips); +} + +BamRecord& BamRecord::InsertionQV(const QualityValues& insertionQVs) +{ + CreateOrEdit(BamRecordTag::INSERTION_QV, insertionQVs.Fastq(), &impl_); + return *this; +} + +Frames BamRecord::IPD(Orientation orientation, bool aligned, bool exciseSoftClips) const +{ + return FetchFrames(BamRecordTag::IPD, orientation, aligned, exciseSoftClips); +} + +BamRecord& BamRecord::IPD(const Frames& frames, const FrameEncodingType encoding) +{ + if (encoding == FrameEncodingType::LOSSY) + CreateOrEdit(BamRecordTag::IPD, frames.Encode(), &impl_); + else + CreateOrEdit(BamRecordTag::IPD, frames.Data(), &impl_); + return *this; +} + +Frames BamRecord::IPDRaw(Orientation orientation) const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::IPD); + const Tag frameTag = impl_.TagValue(tagName); + if (frameTag.IsNull()) return {}; + + Frames frames; + + // lossy frame codes + if (frameTag.IsUInt8Array()) { + const auto codes = frameTag.ToUInt8Array(); + const std::vector codes16(codes.begin(), codes.end()); + frames.Data(std::move(codes16)); + } + + // lossless frame data + else { + assert(frameTag.IsUInt16Array()); + frames.Data(frameTag.ToUInt16Array()); + } + + // return in requested orientation + OrientTagDataAsRequested(&frames, + Orientation::NATIVE, // current + orientation, // requested + impl_.IsReverseStrand()); + return frames; +} + +bool BamRecord::IsMapped() const { return impl_.IsMapped(); } + +QualityValues BamRecord::LabelQV(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchQualities(BamRecordTag::LABEL_QV, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::LabelQV(const QualityValues& labelQVs) +{ + CreateOrEdit(BamRecordTag::LABEL_QV, labelQVs.Fastq(), &impl_); + return *this; +} + +LocalContextFlags BamRecord::LocalContextFlags() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::CONTEXT_FLAGS); + const Tag cxTag = impl_.TagValue(tagName); + return static_cast(cxTag.ToUInt8()); +} + +BamRecord& BamRecord::LocalContextFlags(const PacBio::BAM::LocalContextFlags flags) +{ + CreateOrEdit(BamRecordTag::CONTEXT_FLAGS, static_cast(flags), &impl_); + return *this; +} + +BamRecord& BamRecord::Map(const int32_t referenceId, const Position refStart, const Strand strand, + const Cigar& cigar, const uint8_t mappingQuality) +{ + impl_.Position(refStart); + impl_.ReferenceId(referenceId); + impl_.CigarData(cigar); + impl_.MapQuality(mappingQuality); + impl_.SetMapped(true); + + if (strand == Strand::FORWARD) + impl_.SetReverseStrand(false); + + else { + assert(strand == Strand::REVERSE); + impl_.SetReverseStrand(true); + + // switch seq & qual + std::string sequence = impl_.Sequence(); + QualityValues qualities = impl_.Qualities(); + + ReverseComplement(sequence); + Reverse(qualities); + + impl_.SetSequenceAndQualities(sequence, qualities.Fastq()); + } + + // reset any cached aligned start/end + alignedStart_ = PacBio::BAM::UnmappedPosition; + alignedEnd_ = PacBio::BAM::UnmappedPosition; + + return *this; +} + +BamRecord BamRecord::Mapped(const BamRecord& input, const int32_t referenceId, + const Position refStart, const Strand strand, const Cigar& cigar, + const uint8_t mappingQuality) +{ + return input.Mapped(referenceId, refStart, strand, cigar, mappingQuality); +} + +BamRecord BamRecord::Mapped(const int32_t referenceId, const Position refStart, const Strand strand, + const Cigar& cigar, const uint8_t mappingQuality) const +{ + BamRecord result(*this); + result.Map(referenceId, refStart, strand, cigar, mappingQuality); + return result; +} + +uint8_t BamRecord::MapQuality() const { return impl_.MapQuality(); } + +QualityValues BamRecord::MergeQV(Orientation orientation, bool aligned, bool exciseSoftClips) const +{ + return FetchQualities(BamRecordTag::MERGE_QV, orientation, aligned, exciseSoftClips); +} + +BamRecord& BamRecord::MergeQV(const QualityValues& mergeQVs) +{ + CreateOrEdit(BamRecordTag::MERGE_QV, mergeQVs.Fastq(), &impl_); + return *this; +} + +std::string BamRecord::MovieName() const +{ + const auto& rgId = ReadGroupId(); + if (!rgId.empty()) + return header_.ReadGroup(rgId).MovieName(); + else { + const auto nameParts = Split(FullName(), '/'); + if (nameParts.empty()) + throw std::runtime_error{"BamRecord: has invalid name: '" + FullName() + "'"}; + return nameParts[0]; + } +} + +size_t BamRecord::NumDeletedBases() const +{ + size_t count = 0; + + auto b = BamRecordMemory::GetRawData(this); + uint32_t* cigarData = bam_get_cigar(b.get()); + for (uint32_t i = 0; i < b->core.n_cigar; ++i) { + const auto type = static_cast(bam_cigar_op(cigarData[i])); + if (type == CigarOperationType::DELETION) count += bam_cigar_oplen(cigarData[i]); + } + return count; +} + +size_t BamRecord::NumInsertedBases() const +{ + size_t count = 0; + + auto b = BamRecordMemory::GetRawData(this); + uint32_t* cigarData = bam_get_cigar(b.get()); + for (uint32_t i = 0; i < b->core.n_cigar; ++i) { + const auto type = static_cast(bam_cigar_op(cigarData[i])); + if (type == CigarOperationType::INSERTION) count += bam_cigar_oplen(cigarData[i]); + } + return count; +} + +size_t BamRecord::NumMatches() const { return NumMatchesAndMismatches().first; } + +std::pair BamRecord::NumMatchesAndMismatches() const +{ + std::pair result = std::make_pair(0, 0); + + auto b = BamRecordMemory::GetRawData(this); + uint32_t* cigarData = bam_get_cigar(b.get()); + for (uint32_t i = 0; i < b->core.n_cigar; ++i) { + const auto type = static_cast(bam_cigar_op(cigarData[i])); + if (type == CigarOperationType::SEQUENCE_MATCH) + result.first += bam_cigar_oplen(cigarData[i]); + else if (type == CigarOperationType::SEQUENCE_MISMATCH) + result.second += bam_cigar_oplen(cigarData[i]); + } + return result; +} + +size_t BamRecord::NumMismatches() const { return NumMatchesAndMismatches().second; } + +int32_t BamRecord::NumPasses() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::NUM_PASSES); + const Tag numPasses = impl_.TagValue(tagName); + return numPasses.ToInt32(); +} + +BamRecord& BamRecord::NumPasses(const int32_t numPasses) +{ + CreateOrEdit(BamRecordTag::NUM_PASSES, numPasses, &impl_); + return *this; +} + +std::vector BamRecord::Pkmean(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchPhotons(BamRecordTag::PKMEAN, orientation, aligned, exciseSoftClips, pulseBehavior); +} + +BamRecord& BamRecord::Pkmean(const std::vector& photons) +{ + Pkmean(EncodePhotons(photons)); + return *this; +} + +BamRecord& BamRecord::Pkmean(const std::vector& encodedPhotons) +{ + CreateOrEdit(BamRecordTag::PKMEAN, encodedPhotons, &impl_); + return *this; +} + +std::vector BamRecord::Pkmid(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchPhotons(BamRecordTag::PKMID, orientation, aligned, exciseSoftClips, pulseBehavior); +} + +BamRecord& BamRecord::Pkmid(const std::vector& photons) +{ + Pkmid(EncodePhotons(photons)); + return *this; +} + +BamRecord& BamRecord::Pkmid(const std::vector& encodedPhotons) +{ + CreateOrEdit(BamRecordTag::PKMID, encodedPhotons, &impl_); + return *this; +} + +std::vector BamRecord::Pkmean2(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchPhotons(BamRecordTag::PKMEAN_2, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::Pkmean2(const std::vector& photons) +{ + Pkmean2(EncodePhotons(photons)); + return *this; +} + +BamRecord& BamRecord::Pkmean2(const std::vector& encodedPhotons) +{ + CreateOrEdit(BamRecordTag::PKMEAN_2, encodedPhotons, &impl_); + return *this; +} + +std::vector BamRecord::Pkmid2(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchPhotons(BamRecordTag::PKMID_2, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::Pkmid2(const std::vector& photons) +{ + Pkmid2(EncodePhotons(photons)); + return *this; +} + +BamRecord& BamRecord::Pkmid2(const std::vector& encodedPhotons) +{ + CreateOrEdit(BamRecordTag::PKMID_2, encodedPhotons, &impl_); + return *this; +} + +Frames BamRecord::PreBaseFrames(Orientation orientation, bool aligned, bool exciseSoftClips) const +{ + return IPD(orientation, aligned, exciseSoftClips); +} + +BamRecord& BamRecord::PreBaseFrames(const Frames& frames, const FrameEncodingType encoding) +{ + return IPD(frames, encoding); +} + +Frames BamRecord::PrePulseFrames(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchFrames(BamRecordTag::PRE_PULSE_FRAMES, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::PrePulseFrames(const Frames& frames, const FrameEncodingType encoding) +{ + if (encoding == FrameEncodingType::LOSSY) { + CreateOrEdit(BamRecordTag::PRE_PULSE_FRAMES, frames.Encode(), &impl_); + } else { + CreateOrEdit(BamRecordTag::PRE_PULSE_FRAMES, frames.Data(), &impl_); + } + return *this; +} + +Frames BamRecord::PulseWidthRaw(Orientation orientation, bool /* aligned */, + bool /* exciseSoftClips */) const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::PULSE_WIDTH); + const Tag frameTag = impl_.TagValue(tagName); + if (frameTag.IsNull()) return {}; + + Frames frames; + + // lossy frame codes + if (frameTag.IsUInt8Array()) { + const auto codes = frameTag.ToUInt8Array(); + const std::vector codes16(codes.begin(), codes.end()); + frames.Data(std::move(codes16)); + } + + // lossless frame data + else { + assert(frameTag.IsUInt16Array()); + frames.Data(frameTag.ToUInt16Array()); + } + + // return in requested orientation + OrientTagDataAsRequested(&frames, + Orientation::NATIVE, // current + orientation, // requested + impl_.IsReverseStrand()); + return frames; +} + +QualityValues BamRecord::PulseMergeQV(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchQualities(BamRecordTag::PULSE_MERGE_QV, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::PulseMergeQV(const QualityValues& mergeQVs) +{ + CreateOrEdit(BamRecordTag::PULSE_MERGE_QV, mergeQVs.Fastq(), &impl_); + return *this; +} + +std::string BamRecord::PulseCall(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchBases(BamRecordTag::PULSE_CALL, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::PulseCall(const std::string& tags) +{ + CreateOrEdit(BamRecordTag::PULSE_CALL, tags, &impl_); + return *this; +} + +Frames BamRecord::PulseCallWidth(Orientation orientation, bool aligned, bool exciseSoftClips, + PulseBehavior pulseBehavior) const +{ + return FetchFrames(BamRecordTag::PULSE_CALL_WIDTH, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::PulseCallWidth(const Frames& frames, const FrameEncodingType encoding) +{ + if (encoding == FrameEncodingType::LOSSY) { + CreateOrEdit(BamRecordTag::PULSE_CALL_WIDTH, frames.Encode(), &impl_); + } else { + CreateOrEdit(BamRecordTag::PULSE_CALL_WIDTH, frames.Data(), &impl_); + } + return *this; +} + +std::vector BamRecord::PulseExclusionReason( + Orientation orientation, bool aligned, bool exciseSoftClips, PulseBehavior pulseBehavior) const +{ + std::vector reasons; + + const auto reasonNums = FetchUInt8s(BamRecordTag::PULSE_EXCLUSION, orientation, aligned, + exciseSoftClips, pulseBehavior); + + std::transform( + reasonNums.cbegin(), reasonNums.cend(), std::back_inserter(reasons), + [](const uint8_t num) { return static_cast(num); }); + + return reasons; +} + +BamRecord& BamRecord::PulseExclusionReason( + const std::vector& reasons) +{ + std::vector reasonNums; + std::transform(reasons.cbegin(), reasons.cend(), std::back_inserter(reasonNums), + [](const PacBio::BAM::PulseExclusionReason& reason) { + return static_cast(reason); + }); + + CreateOrEdit(BamRecordTag::PULSE_EXCLUSION, reasonNums, &impl_); + return *this; +} + +Frames BamRecord::PulseWidth(Orientation orientation, bool aligned, bool exciseSoftClips) const +{ + return FetchFrames(BamRecordTag::PULSE_WIDTH, orientation, aligned, exciseSoftClips, + PulseBehavior::ALL); +} + +BamRecord& BamRecord::PulseWidth(const Frames& frames, const FrameEncodingType encoding) +{ + if (encoding == FrameEncodingType::LOSSY) { + CreateOrEdit(BamRecordTag::PULSE_WIDTH, frames.Encode(), &impl_); + } else { + CreateOrEdit(BamRecordTag::PULSE_WIDTH, frames.Data(), &impl_); + } + return *this; +} + +QualityValues BamRecord::Qualities(Orientation orientation, bool aligned, + bool exciseSoftClips) const +{ + return FetchQualities(BamRecordTag::QUAL, orientation, aligned, exciseSoftClips); +} + +Position BamRecord::QueryEnd() const +{ + // try 'qe' tag + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::QUERY_END); + const Tag qe = impl_.TagValue(tagName); + if (!qe.IsNull()) return qe.ToInt32(); + + // tag missing, need to check movie name (fallback for non-PB BAMs, but ignore for CCS reads) + RecordType type; + try { + type = Type(); + } catch (std::exception&) { + return 0; + } + if (type == RecordType::CCS) + throw std::runtime_error{"BamRecord: no query end for CCS read type"}; + if (type == RecordType::TRANSCRIPT) + throw std::runtime_error{"BamRecord: no query end for transcript read type"}; + + // PacBio BAM, non-CCS/transcript + try { + return QueryEndFromName(FullName()); + } catch (std::exception&) { + // return fallback position + return 0; + } +} + +BamRecord& BamRecord::QueryEnd(const Position pos) +{ + CreateOrEdit(BamRecordTag::QUERY_END, static_cast(pos), &impl_); + UpdateName(); + return *this; +} + +int32_t BamRecord::QueryEndFrameNumber() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::QUERY_END_FRAME_NUMBER); + const Tag qs = impl_.TagValue(tagName); + if (!qs.IsNull()) return qs.ToInt32(); + return 0; +} + +BamRecord& BamRecord::QueryEndFrameNumber(const int32_t frameNumber) +{ + CreateOrEdit(BamRecordTag::QUERY_END_FRAME_NUMBER, frameNumber, &impl_); + return *this; +} + +Position BamRecord::QueryStart() const +{ + // try 'qs' tag + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::QUERY_START); + const Tag qs = impl_.TagValue(tagName); + if (!qs.IsNull()) return qs.ToInt32(); + + // tag missing, need to check movie name (fallback for non-PB BAMs, but ignore for CCS reads) + RecordType type; + try { + type = Type(); + } catch (std::exception&) { + return 0; + } + if (type == RecordType::CCS) + throw std::runtime_error{"BamRecord: no query start for CCS read type"}; + if (type == RecordType::TRANSCRIPT) + throw std::runtime_error{"BamRecord: no query start for transcript read type"}; + + // PacBio BAM, non-CCS/transcript + try { + return QueryStartFromName(FullName()); + } catch (std::exception&) { + // return fallback position + return 0; + } +} + +BamRecord& BamRecord::QueryStart(const Position pos) +{ + CreateOrEdit(BamRecordTag::QUERY_START, static_cast(pos), &impl_); + UpdateName(); + return *this; +} + +int32_t BamRecord::QueryStartFrameNumber() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::QUERY_START_FRAME_NUMBER); + const Tag qs = impl_.TagValue(tagName); + if (!qs.IsNull()) return qs.ToInt32(); + return 0; +} + +BamRecord& BamRecord::QueryStartFrameNumber(const int32_t frameNumber) +{ + CreateOrEdit(BamRecordTag::QUERY_START_FRAME_NUMBER, frameNumber, &impl_); + return *this; +} + +Accuracy BamRecord::ReadAccuracy() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::READ_ACCURACY); + const Tag readAccuracy = impl_.TagValue(tagName); + return {readAccuracy.ToFloat()}; +} + +BamRecord& BamRecord::ReadAccuracy(const Accuracy& accuracy) +{ + CreateOrEdit(BamRecordTag::READ_ACCURACY, static_cast(accuracy), &impl_); + return *this; +} + +ReadGroupInfo BamRecord::ReadGroup() const { return header_.ReadGroup(ReadGroupId()); } + +BamRecord& BamRecord::ReadGroup(const ReadGroupInfo& rg) +{ + CreateOrEdit(BamRecordTag::READ_GROUP, rg.Id(), &impl_); + UpdateName(); + return *this; +} + +std::string BamRecord::ReadGroupId() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::READ_GROUP); + const Tag rgTag = impl_.TagValue(tagName); + if (rgTag.IsNull()) return {}; + return rgTag.ToString(); +} + +std::string BamRecord::ReadGroupBaseId() const { return ReadGroup().BaseId(); } + +BamRecord& BamRecord::ReadGroupId(const std::string& id) +{ + CreateOrEdit(BamRecordTag::READ_GROUP, id, &impl_); + UpdateName(); + return *this; +} + +int32_t BamRecord::ReadGroupNumericId() const { return ReadGroupInfo::IdToInt(ReadGroupBaseId()); } + +Position BamRecord::ReferenceEnd() const +{ + if (!impl_.IsMapped()) return PacBio::BAM::UnmappedPosition; + const auto htsData = BamRecordMemory::GetRawData(impl_); + if (!htsData) return PacBio::BAM::UnmappedPosition; + return bam_endpos(htsData.get()); +} + +int32_t BamRecord::ReferenceId() const { return impl_.ReferenceId(); } + +std::string BamRecord::ReferenceName() const +{ + if (IsMapped()) + return Header().SequenceName(ReferenceId()); + else + throw std::runtime_error{"BamRecord: unmapped record has no associated reference name"}; +} + +Position BamRecord::ReferenceStart() const { return impl_.Position(); } + +void BamRecord::ResetCachedPositions() const +{ + alignedEnd_ = PacBio::BAM::UnmappedPosition; + alignedStart_ = PacBio::BAM::UnmappedPosition; +} + +void BamRecord::ResetCachedPositions() +{ + alignedEnd_ = PacBio::BAM::UnmappedPosition; + alignedStart_ = PacBio::BAM::UnmappedPosition; +} + +VirtualRegionType BamRecord::ScrapRegionType() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::SCRAP_REGION_TYPE); + const Tag srTag = impl_.TagValue(tagName); + return VirtualRegionTypeMap::ParseChar[srTag.ToUInt8()]; +} + +BamRecord& BamRecord::ScrapRegionType(const VirtualRegionType type) +{ + CreateOrEdit(BamRecordTag::SCRAP_REGION_TYPE, static_cast(type), &impl_); + return *this; +} + +BamRecord& BamRecord::ScrapRegionType(const char type) +{ + CreateOrEdit(BamRecordTag::SCRAP_REGION_TYPE, type, &impl_); + return *this; +} + +ZmwType BamRecord::ScrapZmwType() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::SCRAP_ZMW_TYPE); + const Tag szTag = impl_.TagValue(tagName); + return ZmwTypeMap::ParseChar[szTag.ToUInt8()]; +} + +BamRecord& BamRecord::ScrapZmwType(const ZmwType type) +{ + CreateOrEdit(BamRecordTag::SCRAP_ZMW_TYPE, static_cast(type), &impl_); + return *this; +} + +BamRecord& BamRecord::ScrapZmwType(const char type) +{ + CreateOrEdit(BamRecordTag::SCRAP_ZMW_TYPE, type, &impl_); + return *this; +} + +std::string BamRecord::Sequence(const Orientation orientation, bool aligned, + bool exciseSoftClips) const +{ + return FetchBases(BamRecordTag::SEQ, orientation, aligned, exciseSoftClips); +} + +std::vector BamRecord::SignalToNoise() const +{ + const auto tagName = BamRecordTags::LabelFor(BamRecordTag::SIGNAL_TO_NOISE); + const Tag snTag = impl_.TagValue(tagName); + return snTag.ToFloatArray(); +} + +BamRecord& BamRecord::SignalToNoise(const std::vector& snr) +{ + CreateOrEdit(BamRecordTag::SIGNAL_TO_NOISE, snr, &impl_); + return *this; +} + +std::vector BamRecord::StartFrame(Orientation orientation, bool aligned, + bool exciseSoftClips, PulseBehavior pulseBehavior) const +{ + return FetchUInt32s(BamRecordTag::START_FRAME, orientation, aligned, exciseSoftClips, + pulseBehavior); +} + +BamRecord& BamRecord::StartFrame(const std::vector& startFrame) +{ + CreateOrEdit(BamRecordTag::START_FRAME, startFrame, &impl_); + return *this; +} + +QualityValues BamRecord::SubstitutionQV(Orientation orientation, bool aligned, + bool exciseSoftClips) const +{ + return FetchQualities(BamRecordTag::SUBSTITUTION_QV, orientation, aligned, exciseSoftClips); +} + +BamRecord& BamRecord::SubstitutionQV(const QualityValues& substitutionQVs) +{ + CreateOrEdit(BamRecordTag::SUBSTITUTION_QV, substitutionQVs.Fastq(), &impl_); + return *this; +} + +std::string BamRecord::SubstitutionTag(Orientation orientation, bool aligned, + bool exciseSoftClips) const +{ + return FetchBases(BamRecordTag::SUBSTITUTION_TAG, orientation, aligned, exciseSoftClips); +} + +BamRecord& BamRecord::SubstitutionTag(const std::string& tags) +{ + CreateOrEdit(BamRecordTag::SUBSTITUTION_TAG, tags, &impl_); + return *this; +} + +Data::Read BamRecord::ToRead() const +{ + Data::Read result{FullName(), Sequence(), Qualities(), + SignalToNoise(), QueryStart(), QueryEnd()}; + + if (HasIPD()) result.IPD = IPD(); + if (HasPulseWidth()) result.PulseWidth = PulseWidth(); + + if (IsMapped() && AlignedStrand() == Data::Strand::REVERSE) { + ReverseComplement(result.Seq); + Reverse(result.Qualities); + } + return result; +} + +Data::MappedRead BamRecord::ToMappedRead() const +{ + if (!IsMapped()) { + throw std::runtime_error{"BAM record '" + FullName() + + "' cannot be converted to MappedRead because it is not mapped"}; + } + + return {ToRead(), AlignedStrand(), ReferenceStart(), ReferenceEnd(), CigarData(), MapQuality()}; +} + +RecordType BamRecord::Type() const +{ + try { + const auto typeName = ReadGroup().ReadType(); + return NameToType(typeName); + } catch (std::exception&) { + + // read group not found, peek at name to see if we're possibly + // CCS or TRANSCRIPT + // + const auto name = FullName(); + if (name.find("transcript") == 0) + return RecordType::TRANSCRIPT; + else if (name.find("/ccs") != std::string::npos) + return RecordType::CCS; + else + return RecordType::UNKNOWN; + } +} + +void BamRecord::UpdateName() +{ + std::string newName; + newName.reserve(100); + + const auto holeNumber = (HasHoleNumber() ? std::to_string(HoleNumber()) : "?"); + if (Type() == RecordType::TRANSCRIPT) { + newName = "transcript/" + holeNumber; + } else { + newName += MovieName(); + newName += "/"; + newName += holeNumber; + newName += "/"; + + if (Type() == RecordType::CCS) + newName += "ccs"; + + else { + if (HasQueryStart()) + newName += std::to_string(QueryStart()); + else + newName += "?"; + + newName += '_'; + + if (HasQueryEnd()) + newName += std::to_string(QueryEnd()); + else + newName += "?"; + } + } + impl_.Name(newName); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamRecordBuilder.cpp b/src/BamRecordBuilder.cpp new file mode 100644 index 0000000..96d8059 --- /dev/null +++ b/src/BamRecordBuilder.cpp @@ -0,0 +1,396 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamRecordBuilder.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "MemoryUtils.h" +#include "pbbam/BamTagCodec.h" + +namespace PacBio { +namespace BAM { + +static_assert(std::is_copy_constructible::value, + "BamRecordBuilder(const BamRecordBuilder&) is not = default"); +static_assert(std::is_copy_assignable::value, + "BamRecordBuilder& operator=(const BamRecordBuilder&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "BamRecordBuilder(BamRecordBuilder&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +BamRecordBuilder::BamRecordBuilder() +{ + // ensure proper clean slate + Reset(); + + // initialize with some space for data + name_.reserve(256); + sequence_.reserve(2096); + qualities_.reserve(2096); + cigar_.reserve(256); +} + +BamRecordBuilder::BamRecordBuilder(BamHeader header) : header_{std::move(header)} +{ + // ensure proper clean slate + Reset(); + + // initialize with some space for data + name_.reserve(256); + sequence_.reserve(2096); + qualities_.reserve(2096); + cigar_.reserve(256); +} + +BamRecordBuilder::BamRecordBuilder(const BamRecord& prototype) : header_{prototype.Header()} +{ + Reset(prototype); +} + +BamRecordBuilder& BamRecordBuilder::Bin(const uint32_t bin) +{ + core_.bin = bin; + return *this; +} + +BamRecord BamRecordBuilder::Build() const +{ + BamRecord result{header_}; + BuildInPlace(result); + return result; +} + +bool BamRecordBuilder::BuildInPlace(BamRecord& record) const +{ + // initialize with basic 'core data' + auto recordRawData = BamRecordMemory::GetRawData(record); + if (!recordRawData || !recordRawData->data) + throw std::runtime_error{ + "BamRecordBuilder: cannot build record, target memory is in an invalid state"}; + recordRawData->core = core_; + + // setup variable length data + const auto encodedTags = BamTagCodec::Encode(tags_); + + const size_t nameLength = name_.size() + 1; + const size_t numCigarOps = cigar_.size(); + const size_t cigarLength = numCigarOps * sizeof(uint32_t); + const size_t seqLength = sequence_.size(); + const size_t qualLength = seqLength; + const size_t tagLength = encodedTags.size(); + const size_t dataLength = nameLength + cigarLength + seqLength + qualLength + tagLength; + + // realloc if necessary + uint8_t* varLengthDataBlock = recordRawData->data; + if (!varLengthDataBlock) + throw std::runtime_error{ + "BamRecordBuilder: cannot build record, target memory is in an invalid state"}; + + size_t allocatedDataLength = recordRawData->m_data; + if (allocatedDataLength < dataLength) { + allocatedDataLength = dataLength; + kroundup32(allocatedDataLength); + varLengthDataBlock = + static_cast(realloc(varLengthDataBlock, allocatedDataLength)); + } + recordRawData->data = varLengthDataBlock; + recordRawData->l_data = dataLength; + recordRawData->m_data = allocatedDataLength; + + size_t index = 0; + + // name + memcpy(&varLengthDataBlock[index], name_.c_str(), nameLength); + index += nameLength; + + // cigar + if (cigarLength > 0) { + std::vector encodedCigar(numCigarOps); + for (size_t i = 0; i < numCigarOps; ++i) { + const auto& op = cigar_.at(i); + encodedCigar[i] = op.Length() << BAM_CIGAR_SHIFT; + const auto type = static_cast(op.Type()); + if (type >= 8) + throw std::runtime_error{"BamRecordBuilder: invalid CIGAR op type: " + + std::to_string(type)}; + encodedCigar[i] |= type; + } + memcpy(&varLengthDataBlock[index], &encodedCigar[0], cigarLength); + index += cigarLength; + + // update bin after we've calculated cigar info + const int32_t endPosition = bam_cigar2rlen(recordRawData->core.n_cigar, &encodedCigar[0]); + recordRawData->core.bin = hts_reg2bin(core_.pos, endPosition, 14, 5); + } + + // seq & qual + if (seqLength > 0) { + + uint8_t* s = &varLengthDataBlock[index]; + for (size_t i = 0; i < seqLength; ++i) + s[i >> 1] |= (seq_nt16_table[static_cast(sequence_.at(i))] << ((~i & 1) << 2)); + index += seqLength; + + uint8_t* q = &varLengthDataBlock[index]; + if (!qualities_.empty()) + memset(q, 0xFF, seqLength); + else { + for (size_t i = 0; i < seqLength; ++i) + q[i] = qualities_.at(i) - 33; + } + index += seqLength; + } + + // tags + if (tagLength > 0) { + if (encodedTags.empty()) + throw std::runtime_error{"BamRecordBuilder: expected tags but none are present"}; + memcpy(&varLengthDataBlock[index], &encodedTags[0], tagLength); + index += tagLength; + } + + // sanity check + if (index != dataLength) { + std::ostringstream s; + s << "BamRecordBuilder: incorrect number of bytes written to record:\n" + << " expected: " << dataLength << '\n' + << " actual: " << index; + throw std::runtime_error{s.str()}; + } + return true; +} + +BamRecordBuilder& BamRecordBuilder::Cigar(PacBio::BAM::Cigar cigar) +{ + core_.n_cigar = cigar.size(); + cigar_ = std::move(cigar); + return *this; +} + +BamRecordBuilder& BamRecordBuilder::Flag(const uint32_t flag) +{ + core_.flag = flag; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::InsertSize(const int32_t iSize) +{ + core_.isize = iSize; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::MapQuality(const uint8_t mapQual) +{ + core_.qual = mapQual; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::MatePosition(const int32_t pos) +{ + core_.mpos = pos; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::MateReferenceId(const int32_t id) +{ + core_.mtid = id; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::Name(std::string name) +{ + core_.l_qname = name.size() + 1; // (NULL-term) + name_ = std::move(name); + return *this; +} + +BamRecordBuilder& BamRecordBuilder::Position(const int32_t pos) +{ + core_.pos = pos; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::Qualities(std::string qualities) +{ + qualities_ = std::move(qualities); + return *this; +} + +BamRecordBuilder& BamRecordBuilder::ReferenceId(const int32_t id) +{ + core_.tid = id; + return *this; +} + +void BamRecordBuilder::Reset() +{ + // zeroize fixed-length data + memset(&core_, 0, sizeof(bam1_core_t)); + core_.l_qname = 1; // always has a NULL-term + + // reset variable-length data + name_.clear(); + sequence_.clear(); + qualities_.clear(); + cigar_.clear(); + tags_.clear(); +} + +void BamRecordBuilder::Reset(BamRecord prototype) +{ + // ensure clean slate + Reset(); + header_ = prototype.Header(); + + // reset variable-length data + const BamRecordImpl& impl = BamRecordMemory::GetImpl(prototype); + name_ = impl.Name(); + sequence_ = impl.Sequence(); + qualities_ = impl.Qualities().Fastq(); + cigar_ = impl.CigarData(); + tags_ = impl.Tags(); + + // reset core data + const auto rawData = BamRecordMemory::GetRawData(prototype); + if (!rawData) + throw std::runtime_error{ + "BamRecordBuilder: cannot build record, target memory is in an invalid state"}; + core_ = std::move(rawData->core); +} + +BamRecordBuilder& BamRecordBuilder::Sequence(std::string sequence) +{ + core_.l_qseq = sequence.size(); + sequence_ = std::move(sequence); + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetDuplicate(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::DUPLICATE; + else + core_.flag &= ~BamRecordImpl::DUPLICATE; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetFailedQC(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::FAILED_QC; + else + core_.flag &= ~BamRecordImpl::FAILED_QC; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetFirstMate(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::MATE_1; + else + core_.flag &= ~BamRecordImpl::MATE_1; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetMapped(bool ok) +{ + if (ok) + core_.flag &= ~BamRecordImpl::UNMAPPED; + else + core_.flag |= BamRecordImpl::UNMAPPED; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetMateMapped(bool ok) +{ + if (ok) + core_.flag &= ~BamRecordImpl::MATE_UNMAPPED; + else + core_.flag |= BamRecordImpl::MATE_UNMAPPED; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetMateReverseStrand(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::MATE_REVERSE_STRAND; + else + core_.flag &= ~BamRecordImpl::MATE_REVERSE_STRAND; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetPaired(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::PAIRED; + else + core_.flag &= ~BamRecordImpl::PAIRED; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetPrimaryAlignment(bool ok) +{ + if (ok) + core_.flag &= ~BamRecordImpl::SECONDARY; + else + core_.flag |= BamRecordImpl::SECONDARY; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetProperPair(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::PROPER_PAIR; + else + core_.flag &= ~BamRecordImpl::PROPER_PAIR; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetReverseStrand(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::REVERSE_STRAND; + else + core_.flag &= ~BamRecordImpl::REVERSE_STRAND; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetSecondMate(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::MATE_2; + else + core_.flag &= ~BamRecordImpl::MATE_2; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::SetSupplementaryAlignment(bool ok) +{ + if (ok) + core_.flag |= BamRecordImpl::SUPPLEMENTARY; + else + core_.flag &= ~BamRecordImpl::SUPPLEMENTARY; + return *this; +} + +BamRecordBuilder& BamRecordBuilder::Tags(TagCollection tags) +{ + tags_ = std::move(tags); + return *this; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamRecordImpl.cpp b/src/BamRecordImpl.cpp new file mode 100644 index 0000000..1281b92 --- /dev/null +++ b/src/BamRecordImpl.cpp @@ -0,0 +1,820 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamRecordImpl.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "BamRecordTags.h" +#include "MemoryUtils.h" +#include "pbbam/BamTagCodec.h" +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { + +namespace { + +static const bool has_native_long_cigar_support = DoesHtslibSupportLongCigar(); + +Cigar FetchRawCigar(const uint32_t* const src, const uint32_t len) +{ + Cigar result; + result.reserve(len); + for (uint32_t i = 0; i < len; ++i) { + const uint32_t length = bam_cigar_oplen(src[i]); + const auto type = static_cast(bam_cigar_op(src[i])); + result.push_back(CigarOperation(type, length)); + } + return result; +} + +bool HasLongCigar(const bam1_t* const b) +{ + auto* c = &b->core; + + // if empty CIGAR or unmapped + if (c->n_cigar == 0 || c->tid < 0 || c->pos < 0) return false; + + // if existing CIGAR doesn't look like a 'fake CIGAR' + const auto firstCigarOp = *(bam_get_cigar(b)); + if (bam_cigar_op(firstCigarOp) != static_cast(CigarOperationType::SOFT_CLIP) || + static_cast(bam_cigar_oplen(firstCigarOp)) != c->l_qseq) { + return false; + } + + // if CG tag missing, not expected type + const uint8_t* const CG = bam_aux_get(b, "CG"); + if (CG == nullptr) return false; + if (CG[0] != 'B' || CG[1] != 'I') return false; + + // if CG tag data is empty + uint32_t numElements = 0; + memcpy(&numElements, &CG[2], sizeof(uint32_t)); + if (numElements == 0) return false; + + // we've found long CIGAR data in the CG tag + return true; +} + +} // namespace + +BamRecordImpl::BamRecordImpl() : d_{nullptr} +{ + InitializeData(); + assert(d_); +} + +BamRecordImpl::BamRecordImpl(const BamRecordImpl& other) + : d_{bam_dup1(other.d_.get()), HtslibRecordDeleter()}, tagOffsets_{other.tagOffsets_} +{ + assert(d_); +} + +BamRecordImpl& BamRecordImpl::operator=(const BamRecordImpl& other) +{ + if (this != &other) { + if (d_ == nullptr) InitializeData(); + bam_copy1(d_.get(), other.d_.get()); + tagOffsets_ = other.tagOffsets_; + } + assert(d_); + return *this; +} + +bool BamRecordImpl::AddTag(const std::string& tagName, const Tag& value) +{ + return AddTag(tagName, value, TagModifier::NONE); +} + +bool BamRecordImpl::AddTag(const BamRecordTag tag, const Tag& value) +{ + return AddTag(BamRecordTags::LabelFor(tag), value, TagModifier::NONE); +} + +bool BamRecordImpl::AddTag(const std::string& tagName, const Tag& value, + const TagModifier additionalModifier) +{ + if (tagName.size() != 2 || HasTag(tagName)) return false; + const auto added = AddTagImpl(tagName, value, additionalModifier); + if (added) UpdateTagMap(); + return added; +} + +bool BamRecordImpl::AddTag(const BamRecordTag tag, const Tag& value, + const TagModifier additionalModifier) +{ + return AddTag(BamRecordTags::LabelFor(tag), value, additionalModifier); +} + +bool BamRecordImpl::AddTagImpl(const std::string& tagName, const Tag& value, + const TagModifier additionalModifier) +{ + const auto rawData = BamTagCodec::ToRawData(value, additionalModifier); + if (rawData.empty()) return false; + + bam_aux_append(d_.get(), tagName.c_str(), BamTagCodec::TagTypeCode(value, additionalModifier), + rawData.size(), const_cast(rawData.data())); + return true; +} + +uint32_t BamRecordImpl::Bin() const { return d_->core.bin; } + +BamRecordImpl& BamRecordImpl::Bin(uint32_t bin) +{ + d_->core.bin = bin; + return *this; +} + +Cigar BamRecordImpl::CigarData() const +{ + const auto* b = d_.get(); + if (!has_native_long_cigar_support && HasLongCigar(b)) { + // fetch long CIGAR from tag + const auto cigarTag = TagValue("CG"); + const auto cigarTagValue = cigarTag.ToUInt32Array(); + return FetchRawCigar(cigarTagValue.data(), cigarTagValue.size()); + } else { + // fetch CIGAR from the standard location + return FetchRawCigar(bam_get_cigar(b), b->core.n_cigar); + } +} + +BamRecordImpl& BamRecordImpl::CigarData(const Cigar& cigar) +{ + // if long CIGAR, using htslib version < 1.7, set it "manually" + if (!has_native_long_cigar_support && cigar.size() >= 65536) { + // Add the 'fake' CIGAR in normal place. + Cigar fake; + fake.emplace_back(CigarOperationType::SOFT_CLIP, SequenceLength()); + const uint32_t alignedLength = + static_cast(bam_cigar2rlen(d_->core.n_cigar, bam_get_cigar(d_.get()))); + fake.emplace_back(CigarOperationType::REFERENCE_SKIP, alignedLength); + SetCigarData(fake); + + // Add raw CIGAR data to CG tag. + std::vector cigarData(cigar.size()); + cigarData.reserve(cigar.size()); + for (size_t i = 0; i < cigar.size(); ++i) { + const CigarOperation& op = cigar.at(i); + cigarData[i] = bam_cigar_gen(op.Length(), static_cast(op.Type())); + } + if (HasTag("CG")) + EditTag("CG", Tag{cigarData}); + else + AddTag("CG", Tag{cigarData}); + } + + // otherwise (v1.7+ or short CIGAR), use standard APIs + else { + if (HasTag("CG")) RemoveTag("CG"); + SetCigarData(cigar); + } + + return *this; +} + +BamRecordImpl& BamRecordImpl::CigarData(const std::string& cigarString) +{ + return CigarData(Cigar::FromStdString(cigarString)); +} + +bool BamRecordImpl::EditTag(const std::string& tagName, const Tag& newValue) +{ + return EditTag(tagName, newValue, TagModifier::NONE); +} + +bool BamRecordImpl::EditTag(const BamRecordTag tag, const Tag& newValue) +{ + return EditTag(BamRecordTags::LabelFor(tag), newValue, TagModifier::NONE); +} + +bool BamRecordImpl::EditTag(const std::string& tagName, const Tag& newValue, + const TagModifier additionalModifier) +{ + // try remove old value (with delayed tag map update) + const bool removed = RemoveTagImpl(tagName); + if (!removed) return false; + + // if old value removed, add new value + const bool added = AddTagImpl(tagName, newValue, additionalModifier); + if (added) UpdateTagMap(); + return added; +} + +bool BamRecordImpl::EditTag(const BamRecordTag tag, const Tag& newValue, + const TagModifier additionalModifier) +{ + return EditTag(BamRecordTags::LabelFor(tag), newValue, additionalModifier); +} + +uint32_t BamRecordImpl::Flag() const { return d_->core.flag; } + +BamRecordImpl& BamRecordImpl::Flag(uint32_t flag) +{ + d_->core.flag = flag; + return *this; +} + +BamRecordImpl BamRecordImpl::FromRawData(const std::shared_ptr& rawData) +{ + BamRecordImpl result; + bam_copy1(result.d_.get(), rawData.get()); + return result; +} + +bool BamRecordImpl::HasTag(const std::string& tagName) const +{ + if (tagName.size() != 2) return false; + return TagOffset(tagName) != -1; +} + +bool BamRecordImpl::HasTag(const BamRecordTag tag) const +{ + return HasTag(BamRecordTags::LabelFor(tag)); +} + +void BamRecordImpl::InitializeData() +{ + d_.reset(bam_init1(), HtslibRecordDeleter()); + d_->data = static_cast( + calloc(0x800, sizeof(uint8_t))); // maybe make this value tune-able later? + d_->m_data = 0x800; + + // init unmapped + Position(PacBio::BAM::UnmappedPosition); + MatePosition(PacBio::BAM::UnmappedPosition); + ReferenceId(-1); + MateReferenceId(-1); + SetMapped(false); + MapQuality(255); + + // initialized with empty qname (null term + 3 'extra nulls' for alignment + d_->core.l_extranul = 3; + d_->core.l_qname = 4; + d_->l_data = 4; +} + +int32_t BamRecordImpl::InsertSize() const { return d_->core.isize; } + +BamRecordImpl& BamRecordImpl::InsertSize(int32_t iSize) +{ + d_->core.isize = iSize; + return *this; +} + +bool BamRecordImpl::IsDuplicate() const { return (d_->core.flag & BamRecordImpl::DUPLICATE) != 0; } + +bool BamRecordImpl::IsFailedQC() const { return (d_->core.flag & BamRecordImpl::FAILED_QC) != 0; } + +bool BamRecordImpl::IsFirstMate() const { return (d_->core.flag & BamRecordImpl::MATE_1) != 0; } + +bool BamRecordImpl::IsMapped() const { return (d_->core.flag & BamRecordImpl::UNMAPPED) == 0; } + +bool BamRecordImpl::IsMateMapped() const +{ + return (d_->core.flag & BamRecordImpl::MATE_UNMAPPED) == 0; +} + +bool BamRecordImpl::IsMateReverseStrand() const +{ + return (d_->core.flag & BamRecordImpl::MATE_REVERSE_STRAND) != 0; +} + +bool BamRecordImpl::IsPaired() const { return (d_->core.flag & BamRecordImpl::PAIRED) != 0; } + +bool BamRecordImpl::IsPrimaryAlignment() const +{ + return (d_->core.flag & BamRecordImpl::SECONDARY) == 0; +} + +bool BamRecordImpl::IsProperPair() const +{ + return (d_->core.flag & BamRecordImpl::PROPER_PAIR) != 0; +} + +bool BamRecordImpl::IsReverseStrand() const +{ + return (d_->core.flag & BamRecordImpl::REVERSE_STRAND) != 0; +} + +bool BamRecordImpl::IsSecondMate() const { return (d_->core.flag & BamRecordImpl::MATE_2) != 0; } + +bool BamRecordImpl::IsSupplementaryAlignment() const +{ + return (d_->core.flag & BamRecordImpl::SUPPLEMENTARY) != 0; +} + +uint8_t BamRecordImpl::MapQuality() const { return d_->core.qual; } + +BamRecordImpl& BamRecordImpl::MapQuality(uint8_t mapQual) +{ + d_->core.qual = mapQual; + return *this; +} + +PacBio::BAM::Position BamRecordImpl::MatePosition() const { return d_->core.mpos; } + +BamRecordImpl& BamRecordImpl::MatePosition(PacBio::BAM::Position pos) +{ + d_->core.mpos = pos; + return *this; +} + +int32_t BamRecordImpl::MateReferenceId() const { return d_->core.mtid; } + +BamRecordImpl& BamRecordImpl::MateReferenceId(int32_t id) +{ + d_->core.mtid = id; + return *this; +} + +PacBio::BAM::Position BamRecordImpl::Position() const { return d_->core.pos; } + +BamRecordImpl& BamRecordImpl::Position(PacBio::BAM::Position pos) +{ + d_->core.pos = pos; + return *this; +} + +int32_t BamRecordImpl::ReferenceId() const { return d_->core.tid; } + +BamRecordImpl& BamRecordImpl::ReferenceId(int32_t id) +{ + d_->core.tid = id; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetDuplicate(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::DUPLICATE; + else + d_->core.flag &= ~BamRecordImpl::DUPLICATE; + return *this; +} + +void BamRecordImpl::MaybeReallocData() +{ + // about to grow data contents to l_data size, but m_data is our current max. + // so we may need to grow. if so, use kroundup to double to next power of 2 + // + // from sam.h: + // decltype(m_data) = uint32_t + // decltype(l_data) = int + if (d_->m_data < static_cast(d_->l_data)) { + d_->m_data = d_->l_data; + kroundup32(d_->m_data); + d_->data = static_cast(realloc(d_->data, d_->m_data)); + } +} + +std::string BamRecordImpl::Name() const { return std::string(bam_get_qname(d_)); } + +BamRecordImpl& BamRecordImpl::Name(const std::string& name) +{ + // determine change in memory needed + // diffNumBytes: pos -> growing, neg -> shrinking + const size_t numChars = name.size() + 1; // +1 for NULL-term + const size_t numExtraNulls = 4 - (numChars % 4); + const size_t totalNameSize = numChars + numExtraNulls; + + const int diffNumBytes = totalNameSize - d_->core.l_qname; + const int oldLengthData = d_->l_data; + d_->l_data += diffNumBytes; + MaybeReallocData(); + + // shift trailing data (cigar, seq, qual, tags) as needed + const uint32_t* oldCigarStart = bam_get_cigar(d_); + const size_t trailingDataLength = + oldLengthData - (reinterpret_cast(oldCigarStart) - + reinterpret_cast(d_->data)); + d_->core.l_qname = totalNameSize; + d_->core.l_extranul = numExtraNulls; + uint32_t* newCigarStart = bam_get_cigar(d_); + memmove(newCigarStart, oldCigarStart, trailingDataLength); + + // fill in new name + memcpy(d_->data, name.c_str(), numChars); + memset(d_->data + numChars, '\0', numExtraNulls); + return *this; +} + +QualityValues BamRecordImpl::Qualities() const +{ + if (d_->core.l_qseq == 0) return QualityValues(); + + uint8_t* qualData = bam_get_qual(d_); + if (qualData[0] == 0xff) return QualityValues(); + + const size_t numQuals = d_->core.l_qseq; + QualityValues result; + result.reserve(numQuals); + for (size_t i = 0; i < numQuals; ++i) + result.push_back(QualityValue(qualData[i])); + return result; +} + +bool BamRecordImpl::RemoveTag(const std::string& tagName) +{ + const bool removed = RemoveTagImpl(tagName); + if (removed) UpdateTagMap(); + return removed; +} + +bool BamRecordImpl::RemoveTag(const BamRecordTag tag) +{ + return RemoveTag(BamRecordTags::LabelFor(tag)); +} + +bool BamRecordImpl::RemoveTagImpl(const std::string& tagName) +{ + if (tagName.size() != 2) return false; + uint8_t* data = bam_aux_get(d_.get(), tagName.c_str()); + if (data == nullptr) return false; + const bool ok = bam_aux_del(d_.get(), data) == 0; + return ok; +} + +std::string BamRecordImpl::Sequence() const +{ + std::string result(d_->core.l_qseq, '\0'); + static const constexpr std::array DnaLookup{ + {'=', 'A', 'C', 'M', 'G', 'R', 'S', 'V', 'T', 'W', 'Y', 'H', 'K', 'D', 'B', 'N'}}; + const uint8_t* seqData = bam_get_seq(d_); + for (int i = 0; i < d_->core.l_qseq; ++i) + result[i] = DnaLookup[bam_seqi(seqData, i)]; + return result; +} + +size_t BamRecordImpl::SequenceLength() const { return d_->core.l_qseq; } + +void BamRecordImpl::SetCigarData(const Cigar& cigar) +{ + // determine change in memory needed + // diffNumBytes: pos -> growing, neg -> shrinking + const size_t numCigarOps = cigar.size(); + const int diffNumCigars = numCigarOps - d_->core.n_cigar; + const int diffNumBytes = diffNumCigars * sizeof(uint32_t); + const int oldLengthData = d_->l_data; + d_->l_data += diffNumBytes; + MaybeReallocData(); + + // shift trailing data (seq, qual, tags) as needed + const uint8_t* oldSequenceStart = bam_get_seq(d_); + const size_t trailingDataLength = oldLengthData - (oldSequenceStart - d_->data); + d_->core.n_cigar = numCigarOps; + uint8_t* newSequenceStart = bam_get_seq(d_); + memmove(newSequenceStart, oldSequenceStart, trailingDataLength); + + // fill in new CIGAR data + uint32_t* cigarDataStart = bam_get_cigar(d_); + for (size_t i = 0; i < numCigarOps; ++i) { + const CigarOperation& cigarOp = cigar.at(i); + cigarDataStart[i] = bam_cigar_gen(cigarOp.Length(), static_cast(cigarOp.Type())); + } +} + +BamRecordImpl& BamRecordImpl::SetFailedQC(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::FAILED_QC; + else + d_->core.flag &= ~BamRecordImpl::FAILED_QC; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetFirstMate(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::MATE_1; + else + d_->core.flag &= ~BamRecordImpl::MATE_1; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetMapped(bool ok) +{ + if (ok) + d_->core.flag &= ~BamRecordImpl::UNMAPPED; + else + d_->core.flag |= BamRecordImpl::UNMAPPED; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetMateMapped(bool ok) +{ + if (ok) + d_->core.flag &= ~BamRecordImpl::MATE_UNMAPPED; + else + d_->core.flag |= BamRecordImpl::MATE_UNMAPPED; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetMateReverseStrand(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::MATE_REVERSE_STRAND; + else + d_->core.flag &= ~BamRecordImpl::MATE_REVERSE_STRAND; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetPaired(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::PAIRED; + else + d_->core.flag &= ~BamRecordImpl::PAIRED; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetPrimaryAlignment(bool ok) +{ + if (ok) + d_->core.flag &= ~BamRecordImpl::SECONDARY; + else + d_->core.flag |= BamRecordImpl::SECONDARY; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetProperPair(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::PROPER_PAIR; + else + d_->core.flag &= ~BamRecordImpl::PROPER_PAIR; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetReverseStrand(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::REVERSE_STRAND; + else + d_->core.flag &= ~BamRecordImpl::REVERSE_STRAND; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetSecondMate(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::MATE_2; + else + d_->core.flag &= ~BamRecordImpl::MATE_2; + return *this; +} + +BamRecordImpl& BamRecordImpl::SetSequenceAndQualities(const std::string& sequence, + const std::string& qualities) +{ + if (!qualities.empty() && (sequence.size() != qualities.size())) { + std::ostringstream s; + s << "BamRecord: if qualities are provided, the length must match the sequence length:\n" + << " seq: " << sequence.size() << '\n' + << " qualities: " << qualities.size(); + throw std::runtime_error{s.str()}; + } + return SetSequenceAndQualitiesInternal(sequence.c_str(), sequence.size(), qualities.c_str(), + false); +} + +BamRecordImpl& BamRecordImpl::SetSequenceAndQualities(const char* sequence, + const size_t sequenceLength, + const char* qualities) +{ + return SetSequenceAndQualitiesInternal(sequence, sequenceLength, qualities, false); +} + +BamRecordImpl& BamRecordImpl::SetPreencodedSequenceAndQualities(const char* encodedSequence, + const size_t rawSequenceLength, + const char* qualities) +{ + return SetSequenceAndQualitiesInternal(encodedSequence, rawSequenceLength, qualities, true); +} + +BamRecordImpl& BamRecordImpl::SetSequenceAndQualitiesInternal(const char* sequence, + const size_t sequenceLength, + const char* qualities, + bool isPreencoded) +{ + // determine change in memory needed + // diffNumBytes: pos -> growing, neg -> shrinking + const auto encodedSequenceLength = static_cast((sequenceLength + 1) / 2); + const int oldSeqAndQualLength = + ((d_->core.l_qseq + 1) / 2) + d_->core.l_qseq; // encoded seq + qual + const int newSeqAndQualLength = encodedSequenceLength + sequenceLength; // encoded seq + qual + const int diffNumBytes = newSeqAndQualLength - oldSeqAndQualLength; + const int oldLengthData = d_->l_data; + d_->l_data += diffNumBytes; + MaybeReallocData(); + + // shift trailing data (tags) as needed + const unsigned char* oldTagStart = bam_get_aux(d_); + const size_t trailingDataLength = + oldLengthData - (oldTagStart - reinterpret_cast(d_->data)); + d_->core.l_qseq = sequenceLength; + uint8_t* newTagStart = bam_get_aux(d_); + memmove(newTagStart, oldTagStart, trailingDataLength); + + // fill in new sequence + uint8_t* pEncodedSequence = bam_get_seq(d_); + if (isPreencoded) { + memcpy(pEncodedSequence, sequence, encodedSequenceLength); + } else { + memset(pEncodedSequence, 0, encodedSequenceLength); + for (size_t i = 0; i < sequenceLength; ++i) + pEncodedSequence[i >> 1] |= seq_nt16_table[static_cast(sequence[i])] + << ((~i & 1) << 2); + } + + // fill in quality values + uint8_t* encodedQualities = bam_get_qual(d_); + if ((qualities == nullptr) || (strlen(qualities) == 0)) + memset(encodedQualities, 0xff, sequenceLength); + else { + for (size_t i = 0; i < sequenceLength; ++i) + encodedQualities[i] = qualities[i] - 33; // FASTQ ASCII -> int conversion + } + return *this; +} + +BamRecordImpl& BamRecordImpl::SetSupplementaryAlignment(bool ok) +{ + if (ok) + d_->core.flag |= BamRecordImpl::SUPPLEMENTARY; + else + d_->core.flag &= ~BamRecordImpl::SUPPLEMENTARY; + return *this; +} + +int BamRecordImpl::TagOffset(const std::string& tagName) const +{ + if (tagName.size() != 2) + throw std::runtime_error{"BamRecord: tag name (" + tagName + + ") must have 2 characters only"}; + + if (tagOffsets_.empty()) UpdateTagMap(); + + const uint16_t tagCode = + (static_cast(tagName.at(0)) << 8) | static_cast(tagName.at(1)); + const auto found = tagOffsets_.find(tagCode); + return (found != tagOffsets_.cend() ? found->second : -1); +} + +BamRecordImpl& BamRecordImpl::Tags(const TagCollection& tags) +{ + // convert tags to binary + const std::vector tagData = BamTagCodec::Encode(tags); + const size_t numBytes = tagData.size(); + const uint8_t* data = tagData.data(); + + // determine change in memory needed + uint8_t* tagStart = bam_get_aux(d_); + const size_t oldNumBytes = d_->l_data - (tagStart - d_->data); + const int diffNumBytes = numBytes - oldNumBytes; + d_->l_data += diffNumBytes; + MaybeReallocData(); + tagStart = bam_get_aux(d_); + + // fill in new tag data + memcpy(static_cast(tagStart), data, numBytes); + + // update tag info + UpdateTagMap(); + return *this; +} + +TagCollection BamRecordImpl::Tags() const +{ + const uint8_t* tagDataStart = bam_get_aux(d_); + const size_t numBytes = d_->l_data - (tagDataStart - d_->data); + return BamTagCodec::Decode(std::vector(tagDataStart, tagDataStart + numBytes)); +} + +Tag BamRecordImpl::TagValue(const std::string& tagName) const +{ + if (tagName.size() != 2) return {}; + + const int offset = TagOffset(tagName); + if (offset == -1) return {}; + + bam1_t* b = d_.get(); + assert(bam_get_aux(b)); + uint8_t* tagData = bam_get_aux(b) + offset; + if (offset >= b->l_data) return {}; + + // skip tag name + return BamTagCodec::FromRawData(tagData); +} + +Tag BamRecordImpl::TagValue(const BamRecordTag tag) const +{ + return TagValue(BamRecordTags::LabelFor(tag)); +} + +void BamRecordImpl::UpdateTagMap() const +{ + // clear out offsets, leave map structure basically intact + for (auto& tag : tagOffsets_) + tag.second = -1; + + const uint8_t* tagStart = bam_get_aux(d_); + if (tagStart == nullptr) return; + const ptrdiff_t numBytes = d_->l_data - (tagStart - d_->data); + + // NOTE: using a 16-bit 'code' for tag name here instead of string, to avoid + // a lot of string constructions & comparisons. All valid tags will be 2 chars + // anyway, so this should be a nice lookup mechanism. + // + uint16_t tagNameCode; + int64_t i = 0; + while (i < numBytes) { + + // store (tag name code -> start offset into tag data) + tagNameCode = static_cast(tagStart[i]) << 8 | static_cast(tagStart[i + 1]); + i += 2; + tagOffsets_[tagNameCode] = i; + + // skip tag contents + const auto tagType = static_cast(tagStart[i++]); + switch (tagType) { + case 'A': + case 'a': + case 'c': + case 'C': { + i += 1; + break; + } + case 's': + case 'S': { + i += 2; + break; + } + case 'i': + case 'I': + case 'f': { + i += 4; + break; + } + + case 'Z': + case 'H': { + // null-terminated string + i += strlen(reinterpret_cast(&tagStart[i])) + 1; + break; + } + + case 'B': { + const char subTagType = tagStart[i++]; + size_t elementSize = 0; + switch (subTagType) { + case 'c': + case 'C': + elementSize = 1; + break; + case 's': + case 'S': + elementSize = 2; + break; + case 'i': + case 'I': + case 'f': + elementSize = 4; + break; + + // unknown subTagType + default: + throw std::runtime_error{ + "BamRecord: unsupported array-tag-type encountered: " + + std::string{1, subTagType}}; + } + + uint32_t numElements = 0; + memcpy(&numElements, &tagStart[i], sizeof(uint32_t)); + i += (4 + (elementSize * numElements)); + break; + } + + // unknown tagType + default: + throw std::runtime_error{"BamRecord: unsupported tag-type encountered: " + + std::string{1, tagType}}; + } + } +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamRecordTags.cpp b/src/BamRecordTags.cpp new file mode 100644 index 0000000..731c7a1 --- /dev/null +++ b/src/BamRecordTags.cpp @@ -0,0 +1,66 @@ +// File Description +/// \file BamRecordTags.h +/// \brief Implements the BamRecordTags utility class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "BamRecordTags.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +// clang-format off +const BamRecordTags::TagLookupType BamRecordTags::tagLookup = +{ + // enum name label isPulse? + // --------- ----- -------- + { BamRecordTag::ALT_LABEL_QV, {"pv", true} }, + { BamRecordTag::ALT_LABEL_TAG, {"pt", true} }, + { BamRecordTag::BARCODE_QUALITY, {"bq", false} }, + { BamRecordTag::BARCODES, {"bc", false} }, + { BamRecordTag::CONTEXT_FLAGS, {"cx", false} }, + { BamRecordTag::DELETION_QV, {"dq", false} }, + { BamRecordTag::DELETION_TAG, {"dt", false} }, + { BamRecordTag::HOLE_NUMBER, {"zm", false} }, + { BamRecordTag::INSERTION_QV, {"iq", false} }, + { BamRecordTag::IPD, {"ip", false} }, + { BamRecordTag::LABEL_QV, {"pq", true} }, + { BamRecordTag::LONG_CIGAR, {"CG", false} }, + { BamRecordTag::MERGE_QV, {"mq", false} }, + { BamRecordTag::NUM_PASSES, {"np", false} }, + { BamRecordTag::PKMEAN, {"pa", true} }, + { BamRecordTag::PKMEAN_2, {"ps", true} }, + { BamRecordTag::PKMID, {"pm", true} }, + { BamRecordTag::PKMID_2, {"pi", true} }, + { BamRecordTag::PRE_PULSE_FRAMES, {"pd", true} }, + { BamRecordTag::PULSE_CALL, {"pc", true} }, + { BamRecordTag::PULSE_CALL_WIDTH, {"px", true} }, + { BamRecordTag::PULSE_EXCLUSION, {"pe", true} }, + { BamRecordTag::PULSE_MERGE_QV, {"pg", true} }, + { BamRecordTag::PULSE_WIDTH, {"pw", false} }, // 'pulse' in the name; but stored per-base, not per-pulse + { BamRecordTag::QUERY_END, {"qe", false} }, + { BamRecordTag::QUERY_END_FRAME_NUMBER, {"we", false} }, + { BamRecordTag::QUERY_START, {"qs", false} }, + { BamRecordTag::QUERY_START_FRAME_NUMBER, {"ws", false} }, + { BamRecordTag::READ_ACCURACY, {"rq", false} }, + { BamRecordTag::READ_GROUP, {"RG", false} }, + { BamRecordTag::SCRAP_REGION_TYPE, {"sc", false} }, + { BamRecordTag::SCRAP_ZMW_TYPE, {"sz", false} }, + { BamRecordTag::SIGNAL_TO_NOISE, {"sn", false} }, + { BamRecordTag::START_FRAME, {"sf", true} }, + { BamRecordTag::SUBSTITUTION_QV, {"sq", false} }, + { BamRecordTag::SUBSTITUTION_TAG, {"st", false} }, + + // faux tags + { BamRecordTag::SEQ, {" ", false} }, + { BamRecordTag::QUAL, {" ", false} } +}; +// clang-format on + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamRecordTags.h b/src/BamRecordTags.h new file mode 100644 index 0000000..0b31bdc --- /dev/null +++ b/src/BamRecordTags.h @@ -0,0 +1,56 @@ +// File Description +/// \file BamRecordTags.h +/// \brief Defines the BamRecordTags utility class. +// +// Author: Derek Barnett + +#ifndef BAMRECORDTAGS_H +#define BAMRECORDTAGS_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include +#include +#include + +namespace PacBio { +namespace BAM { + +class BamRecordTags +{ +public: + // tag info + static inline bool IsPulse(const BamRecordTag tag); + static inline std::string LabelFor(const BamRecordTag tag); + +private: + struct BamRecordTagData + { + const std::string label_; //[3]; // 2-char tag plus NULL + const bool isPulse_; + }; + + using TagLookupType = std::unordered_map; + static const TagLookupType tagLookup; +}; + +inline bool BamRecordTags::IsPulse(const BamRecordTag tag) +{ + assert(tagLookup.find(tag) != tagLookup.cend()); + return tagLookup.at(tag).isPulse_; +} + +inline std::string BamRecordTags::LabelFor(const BamRecordTag tag) +{ + assert(tagLookup.find(tag) != tagLookup.cend()); + return tagLookup.at(tag).label_; +} + +} // namespace BAM +} // namespace PacBio + +#endif // BAMRECORDTAGS_H diff --git a/src/BamRecordView.cpp b/src/BamRecordView.cpp new file mode 100644 index 0000000..a08b7d4 --- /dev/null +++ b/src/BamRecordView.cpp @@ -0,0 +1,138 @@ +// File Description +/// \file BamRecordView.cpp +/// \brief Implements the BamRecordTags utility class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamRecordView.h" + +namespace PacBio { +namespace BAM { + +BamRecordView::BamRecordView(const BamRecord& record, const Orientation orientation, + const bool aligned, const bool exciseSoftClips, + const PulseBehavior pulseBehavior) + : record_(record) + , orientation_{orientation} + , aligned_{aligned} + , exciseSoftClips_{exciseSoftClips} + , pulseBehavior_{pulseBehavior} +{ +} + +QualityValues BamRecordView::AltLabelQVs() const +{ + return record_.AltLabelQV(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +std::string BamRecordView::AltLabelTags() const +{ + return record_.AltLabelTag(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +QualityValues BamRecordView::DeletionQVs() const +{ + return record_.DeletionQV(orientation_, aligned_, exciseSoftClips_); +} + +std::string BamRecordView::DeletionTags() const +{ + return record_.DeletionTag(orientation_, aligned_, exciseSoftClips_); +} + +QualityValues BamRecordView::InsertionQVs() const +{ + return record_.InsertionQV(orientation_, aligned_, exciseSoftClips_); +} + +Frames BamRecordView::IPD() const { return record_.IPD(orientation_, aligned_, exciseSoftClips_); } + +Frames BamRecordView::PrebaseFrames() const +{ + return record_.IPD(orientation_, aligned_, exciseSoftClips_); +} + +QualityValues BamRecordView::LabelQVs() const +{ + return record_.LabelQV(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +QualityValues BamRecordView::MergeQVs() const +{ + return record_.MergeQV(orientation_, aligned_, exciseSoftClips_); +} + +QualityValues BamRecordView::PulseMergeQVs() const +{ + return record_.PulseMergeQV(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +std::vector BamRecordView::Pkmean() const +{ + return record_.Pkmean(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +std::vector BamRecordView::Pkmid() const +{ + return record_.Pkmid(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +std::vector BamRecordView::Pkmean2() const +{ + return record_.Pkmean2(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +std::vector BamRecordView::Pkmid2() const +{ + return record_.Pkmid2(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +Frames BamRecordView::PrePulseFrames() const +{ + return record_.PrePulseFrames(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +std::string BamRecordView::PulseCalls() const +{ + return record_.PulseCall(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +Frames BamRecordView::PulseCallWidth() const +{ + return record_.PulseCallWidth(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +Frames BamRecordView::PulseWidths() const +{ + return record_.PulseWidth(orientation_, aligned_, exciseSoftClips_); +} + +QualityValues BamRecordView::Qualities() const +{ + return record_.Qualities(orientation_, aligned_, exciseSoftClips_); +} + +std::string BamRecordView::Sequence() const +{ + return record_.Sequence(orientation_, aligned_, exciseSoftClips_); +} + +std::vector BamRecordView::StartFrames() const +{ + return record_.StartFrame(orientation_, aligned_, exciseSoftClips_, pulseBehavior_); +} + +QualityValues BamRecordView::SubstitutionQVs() const +{ + return record_.SubstitutionQV(orientation_, aligned_, exciseSoftClips_); +} + +std::string BamRecordView::SubstitutionTags() const +{ + return record_.SubstitutionTag(orientation_, aligned_, exciseSoftClips_); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamTagCodec.cpp b/src/BamTagCodec.cpp new file mode 100644 index 0000000..42fa048 --- /dev/null +++ b/src/BamTagCodec.cpp @@ -0,0 +1,546 @@ +// File Description +/// \file BamTagCodec.cpp +/// \brief Implements the BamTagCodec class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamTagCodec.h" + +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { +namespace { + +template +inline void appendBamValue(const T& value, kstring_t* str) +{ + kputsn_(reinterpret_cast(&value), sizeof(value), str); +} + +template +inline void appendBamMultiValue(const std::vector& container, kstring_t* str) +{ + const uint32_t n = container.size(); + kputsn_(&n, sizeof(n), str); + kputsn_(reinterpret_cast(&container[0]), n * sizeof(T), str); +} + +template +inline T readBamValue(const uint8_t* src, size_t& offset) +{ + T value; + memcpy(&value, &src[offset], sizeof(value)); + offset += sizeof(value); + return value; +} + +template +std::vector readBamMultiValue(const uint8_t* src, size_t& offset) +{ + uint32_t numElements; + memcpy(&numElements, &src[offset], sizeof(uint32_t)); + offset += 4; + + std::vector result; + result.reserve(numElements); + for (size_t i = 0; i < numElements; ++i) { + const T value = readBamValue(src, offset); + result.push_back(value); + } + return result; +} + +} // anonymous + +TagCollection BamTagCodec::Decode(const std::vector& data) +{ + TagCollection tags; + + // NOTE: not completely safe - no real bounds-checking yet on input data + + const uint8_t* pData = data.data(); + const size_t numBytes = data.size(); + size_t i = 0; + while (i < numBytes) { + + std::string tagName; + tagName.reserve(2); + tagName.append(1, pData[i++]); + tagName.append(1, pData[i++]); + + const auto tagType = static_cast(pData[i++]); + switch (tagType) { + case 'A': + case 'a': { + tags[tagName] = readBamValue(pData, i); + tags[tagName].Modifier(TagModifier::ASCII_CHAR); + break; + } + + case 'c': + tags[tagName] = readBamValue(pData, i); + break; + case 'C': + tags[tagName] = readBamValue(pData, i); + break; + case 's': + tags[tagName] = readBamValue(pData, i); + break; + case 'S': + tags[tagName] = readBamValue(pData, i); + break; + case 'i': + tags[tagName] = readBamValue(pData, i); + break; + case 'I': + tags[tagName] = readBamValue(pData, i); + break; + case 'f': + tags[tagName] = readBamValue(pData, i); + break; + + case 'Z': + case 'H': { + const size_t dataLength = strlen(reinterpret_cast(&pData[i])); + std::string value(reinterpret_cast(&pData[i]), dataLength); + tags[tagName] = value; + if (tagType == 'H') tags[tagName].Modifier(TagModifier::HEX_STRING); + i += dataLength + 1; + break; + } + + case 'B': { + const char subTagType = pData[i++]; + switch (subTagType) { + case 'c': + tags[tagName] = readBamMultiValue(pData, i); + break; + case 'C': + tags[tagName] = readBamMultiValue(pData, i); + break; + case 's': + tags[tagName] = readBamMultiValue(pData, i); + break; + case 'S': + tags[tagName] = readBamMultiValue(pData, i); + break; + case 'i': + tags[tagName] = readBamMultiValue(pData, i); + break; + case 'I': + tags[tagName] = readBamMultiValue(pData, i); + break; + case 'f': + tags[tagName] = readBamMultiValue(pData, i); + break; + + // unknown subTagType + default: + throw std::runtime_error{ + "BamTagCodec: unsupported array-tag-type encountered: " + + std::string{1, subTagType}}; + } + break; + } + + // unknown tagType + default: + throw std::runtime_error{"BamTagCodec: unsupported tag-type encountered: " + + std::string{1, tagType}}; + } + } + + return tags; +} + +std::vector BamTagCodec::Encode(const TagCollection& tags) +{ + kstring_t str = {0, 0, nullptr}; + + for (const auto& tagIter : tags) { + + const auto& name = tagIter.first; + if (name.size() != 2) + throw std::runtime_error{"BamTagCodec: tag name (" + name + + ") must have 2 characters only"}; + + const auto& tag = tagIter.second; + if (tag.IsNull()) continue; + + // ":" + kputsn_(name.c_str(), 2, &str); + + // ":" for printable, ASCII char + if (tag.HasModifier(TagModifier::ASCII_CHAR)) { + const char c = tag.ToAscii(); + if (c != '\0') { + kputc_('A', &str); + kputc_(c, &str); + continue; + } + } + + // ":" for all other data + switch (tag.Type()) { + case TagDataType::INT8: { + kputc_('c', &str); + appendBamValue(tag.ToInt8(), &str); + break; + } + case TagDataType::UINT8: { + kputc_('C', &str); + appendBamValue(tag.ToUInt8(), &str); + break; + } + case TagDataType::INT16: { + kputc_('s', &str); + appendBamValue(tag.ToInt16(), &str); + break; + } + case TagDataType::UINT16: { + kputc_('S', &str); + appendBamValue(tag.ToUInt16(), &str); + break; + } + case TagDataType::INT32: { + kputc_('i', &str); + appendBamValue(tag.ToInt32(), &str); + break; + } + case TagDataType::UINT32: { + kputc_('I', &str); + appendBamValue(tag.ToUInt32(), &str); + break; + } + case TagDataType::FLOAT: { + kputc_('f', &str); + appendBamValue(tag.ToFloat(), &str); + break; + } + + case TagDataType::STRING: { + if (tag.HasModifier(TagModifier::HEX_STRING)) + kputc_('H', &str); + else + kputc_('Z', &str); + const auto s = tag.ToString(); + kputsn_(s.c_str(), s.size() + 1, &str); // this adds the null-term + break; + } + + case TagDataType::INT8_ARRAY: { + kputc_('B', &str); + kputc_('c', &str); + appendBamMultiValue(tag.ToInt8Array(), &str); + break; + } + case TagDataType::UINT8_ARRAY: { + kputc_('B', &str); + kputc_('C', &str); + appendBamMultiValue(tag.ToUInt8Array(), &str); + break; + } + case TagDataType::INT16_ARRAY: { + kputc_('B', &str); + kputc_('s', &str); + appendBamMultiValue(tag.ToInt16Array(), &str); + break; + } + case TagDataType::UINT16_ARRAY: { + kputc_('B', &str); + kputc_('S', &str); + appendBamMultiValue(tag.ToUInt16Array(), &str); + break; + } + case TagDataType::INT32_ARRAY: { + kputc_('B', &str); + kputc_('i', &str); + appendBamMultiValue(tag.ToInt32Array(), &str); + break; + } + case TagDataType::UINT32_ARRAY: { + kputc_('B', &str); + kputc_('I', &str); + appendBamMultiValue(tag.ToUInt32Array(), &str); + break; + } + case TagDataType::FLOAT_ARRAY: { + kputc_('B', &str); + kputc_('f', &str); + appendBamMultiValue(tag.ToFloatArray(), &str); + break; + } + + // unsupported tag type + default: { + free(str.s); + throw std::runtime_error{"BamTagCodec: unsupported tag-type encountered: " + + std::to_string(static_cast(tag.Type()))}; + } + } + } + + std::vector result; + result.resize(str.l); + memcpy(reinterpret_cast(result.data()), str.s, str.l); + free(str.s); + return result; +} + +Tag BamTagCodec::FromRawData(uint8_t* rawData) +{ + size_t offset = 0; + const auto tagType = static_cast(*rawData++); + switch (tagType) { + case 'A': + case 'a': { + Tag t{readBamValue(rawData, offset)}; + t.Modifier(TagModifier::ASCII_CHAR); + return t; + } + + case 'c': + return {readBamValue(rawData, offset)}; + case 'C': + return {readBamValue(rawData, offset)}; + case 's': + return {readBamValue(rawData, offset)}; + case 'S': + return {readBamValue(rawData, offset)}; + case 'i': + return {readBamValue(rawData, offset)}; + case 'I': + return {readBamValue(rawData, offset)}; + case 'f': + return {readBamValue(rawData, offset)}; + + case 'Z': + case 'H': { + const size_t dataLength = strlen(reinterpret_cast(&rawData[0])); + std::string value(reinterpret_cast(&rawData[0]), dataLength); + Tag t{value}; + if (tagType == 'H') t.Modifier(TagModifier::HEX_STRING); + return t; + } + + case 'B': { + const char subTagType = *rawData++; + switch (subTagType) { + + case 'c': + return {readBamMultiValue(rawData, offset)}; + case 'C': + return {readBamMultiValue(rawData, offset)}; + case 's': + return {readBamMultiValue(rawData, offset)}; + case 'S': + return {readBamMultiValue(rawData, offset)}; + case 'i': + return {readBamMultiValue(rawData, offset)}; + case 'I': + return {readBamMultiValue(rawData, offset)}; + case 'f': + return {readBamMultiValue(rawData, offset)}; + + // unknown subTagType + default: + throw std::runtime_error{ + "BamTagCodec: unsupported array-tag-type encountered: " + + std::string{1, subTagType}}; + } + break; + } + + // unknown tagType + default: + throw std::runtime_error{"BamTagCodec: unsupported tag-type encountered: " + + std::string{1, tagType}}; + } + return Tag(); // to avoid compiler warning +} + +std::vector BamTagCodec::ToRawData(const Tag& tag, const TagModifier& additionalModifier) +{ + // temp raw data destination (for use with htslib methods) + kstring_t str = {0, 0, nullptr}; + + // ":" for printable, ASCII char + if (tag.HasModifier(TagModifier::ASCII_CHAR) || additionalModifier == TagModifier::ASCII_CHAR) { + const char c = tag.ToAscii(); + if (c != '\0') kputc_(c, &str); + } + + // for all others + else { + switch (tag.Type()) { + + // single, numeric values + case TagDataType::INT8: + appendBamValue(tag.ToInt8(), &str); + break; + case TagDataType::UINT8: + appendBamValue(tag.ToUInt8(), &str); + break; + case TagDataType::INT16: + appendBamValue(tag.ToInt16(), &str); + break; + case TagDataType::UINT16: + appendBamValue(tag.ToUInt16(), &str); + break; + case TagDataType::INT32: + appendBamValue(tag.ToInt32(), &str); + break; + case TagDataType::UINT32: + appendBamValue(tag.ToUInt32(), &str); + break; + case TagDataType::FLOAT: + appendBamValue(tag.ToFloat(), &str); + break; + + // string & hex-string values + case TagDataType::STRING: { + const auto s = tag.ToString(); + kputsn_(s.c_str(), s.size() + 1, &str); // this adds the null-term + break; + } + + // array-type values + case TagDataType::INT8_ARRAY: { + kputc_('c', &str); + appendBamMultiValue(tag.ToInt8Array(), &str); + break; + } + case TagDataType::UINT8_ARRAY: { + kputc_('C', &str); + appendBamMultiValue(tag.ToUInt8Array(), &str); + break; + } + case TagDataType::INT16_ARRAY: { + kputc_('s', &str); + appendBamMultiValue(tag.ToInt16Array(), &str); + break; + } + case TagDataType::UINT16_ARRAY: { + kputc_('S', &str); + appendBamMultiValue(tag.ToUInt16Array(), &str); + break; + } + case TagDataType::INT32_ARRAY: { + kputc_('i', &str); + appendBamMultiValue(tag.ToInt32Array(), &str); + break; + } + case TagDataType::UINT32_ARRAY: { + kputc_('I', &str); + appendBamMultiValue(tag.ToUInt32Array(), &str); + break; + } + case TagDataType::FLOAT_ARRAY: { + kputc_('f', &str); + appendBamMultiValue(tag.ToFloatArray(), &str); + break; + } + + // unsupported tag type + default: { + free(str.s); + throw std::runtime_error{"BamTagCodec: unsupported tag-type encountered: " + + std::to_string(static_cast(tag.Type()))}; + } + } + } + + // store temp contents in actual destination + std::vector result; + result.resize(str.l); + memcpy(reinterpret_cast(&result[0]), str.s, str.l); + free(str.s); + return result; +} + +uint8_t BamTagCodec::TagTypeCode(const Tag& tag, const TagModifier& additionalModifier) +{ + if (tag.HasModifier(TagModifier::ASCII_CHAR) || additionalModifier == TagModifier::ASCII_CHAR) { + int64_t value = 0; + switch (tag.Type()) { + case TagDataType::INT8: + value = static_cast(tag.ToInt8()); + break; + case TagDataType::UINT8: + value = static_cast(tag.ToUInt8()); + break; + case TagDataType::INT16: + value = static_cast(tag.ToInt16()); + break; + case TagDataType::UINT16: + value = static_cast(tag.ToUInt16()); + break; + case TagDataType::INT32: + value = static_cast(tag.ToInt32()); + break; + case TagDataType::UINT32: + value = static_cast(tag.ToUInt32()); + break; + default: + // non integers not allowed + throw std::runtime_error{ + "BamTagCodec: tag-type not convertible to ASCII, tag-type: " + + std::to_string(static_cast(tag.Type()))}; + } + + // ensure value is in valid ASCII char range + if (value < 33 || value > 126) + throw std::runtime_error{"BamTagCodec: invalid integer value for ASCII char, value: " + + std::to_string(value)}; + + return static_cast('A'); + } + + switch (tag.Type()) { + case TagDataType::INT8: + return static_cast('c'); + case TagDataType::UINT8: + return static_cast('C'); + case TagDataType::INT16: + return static_cast('s'); + case TagDataType::UINT16: + return static_cast('S'); + case TagDataType::INT32: + return static_cast('i'); + case TagDataType::UINT32: + return static_cast('I'); + case TagDataType::FLOAT: + return static_cast('f'); + + case TagDataType::STRING: { + if (tag.HasModifier(TagModifier::HEX_STRING) || + additionalModifier == TagModifier::HEX_STRING) + return static_cast('H'); + return static_cast('Z'); + } + + case TagDataType::INT8_ARRAY: // fall through + case TagDataType::UINT8_ARRAY: // . + case TagDataType::INT16_ARRAY: // . + case TagDataType::UINT16_ARRAY: // . + case TagDataType::INT32_ARRAY: // . + case TagDataType::UINT32_ARRAY: // . + case TagDataType::FLOAT_ARRAY: + return static_cast('B'); + + default: + throw std::runtime_error{"BamTagCodec: unsupported tag-type encountered: " + + std::to_string(static_cast(tag.Type()))}; + } + return 0; // to avoid compiler warning +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BamWriter.cpp b/src/BamWriter.cpp new file mode 100644 index 0000000..3422e14 --- /dev/null +++ b/src/BamWriter.cpp @@ -0,0 +1,166 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BamWriter.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Autovalidate.h" +#include "FileProducer.h" +#include "MemoryUtils.h" +#include "pbbam/BamFile.h" +#include "pbbam/Unused.h" +#include "pbbam/Validator.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "BamWriter(const BamWriter&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "BamWriter& operator=(const BamWriter&) is not = delete"); + +class BamWriter::BamWriterPrivate +{ +public: + BamWriterPrivate(const std::string& filename, const std::shared_ptr rawHeader, + const BamWriter::CompressionLevel compressionLevel, const size_t numThreads, + const BamWriter::BinCalculationMode binCalculationMode, const bool useTempFile) + : calculateBins_{binCalculationMode == BamWriter::BinCalculation_ON}, header_{rawHeader} + { + if (!header_) throw std::runtime_error{"BamWriter: null header provided for: " + filename}; + + if (useTempFile) fileProducer_ = std::make_unique(filename); + + // open file + const auto usingFilename = (fileProducer_ ? fileProducer_->TempFilename() : filename); + const auto mode = std::string("wb") + std::to_string(static_cast(compressionLevel)); + file_.reset(sam_open(usingFilename.c_str(), mode.c_str())); + if (!file_) + throw std::runtime_error{"BamWriter: could not open BAM file for writing: " + + usingFilename}; + + // if no explicit thread count given, attempt built-in check + size_t actualNumThreads = numThreads; + if (actualNumThreads == 0) { + actualNumThreads = std::thread::hardware_concurrency(); + + // if still unknown, default to single-threaded + if (actualNumThreads == 0) actualNumThreads = 1; + } + + // if multithreading requested, enable it + if (actualNumThreads > 1) hts_set_threads(file_.get(), actualNumThreads); + + // write header + const auto ret = sam_hdr_write(file_.get(), header_.get()); + if (ret != 0) + throw std::runtime_error{"BamWriter: could not write header for file: " + + usingFilename}; + } + + void Write(const BamRecord& record) + { +#if PBBAM_AUTOVALIDATE + Validator::Validate(record); +#endif + + const auto rawRecord = BamRecordMemory::GetRawData(record); + + // (probably) store bins + // min_shift=14 & n_lvls=5 are BAM "magic numbers" + if (calculateBins_) + rawRecord->core.bin = + hts_reg2bin(rawRecord->core.pos, bam_endpos(rawRecord.get()), 14, 5); + + // write record to file + const auto ret = sam_write1(file_.get(), header_.get(), rawRecord.get()); + if (ret <= 0) throw std::runtime_error{"BamWriter: could not write record to file"}; + } + + void Write(const BamRecord& record, int64_t* vOffset) + { + BGZF* bgzf = file_.get()->fp.bgzf; + assert(bgzf); + assert(vOffset); + + // ensure offsets up-to-date + const auto ret = bgzf_flush(bgzf); + UNUSED(ret); + + // capture virtual offset where we’re about to write + const auto rawTell = htell(bgzf->fp); + const auto length = bgzf->block_offset; + *vOffset = (rawTell << 16) | length; + + // now write data + Write(record); + } + + void Write(const BamRecordImpl& recordImpl) { Write(BamRecord(recordImpl)); } + + bool calculateBins_; + std::unique_ptr file_; + std::shared_ptr header_; + std::unique_ptr fileProducer_; +}; + +BamWriter::BamWriter(const std::string& filename, const BamHeader& header, + const BamWriter::CompressionLevel compressionLevel, const size_t numThreads, + const BinCalculationMode binCalculationMode, const bool useTempFile) + : IRecordWriter() +{ +#if PBBAM_AUTOVALIDATE + Validator::Validate(header); +#endif + d_ = std::make_unique(filename, BamHeaderMemory::MakeRawHeader(header), + compressionLevel, numThreads, binCalculationMode, + useTempFile); +} + +BamWriter::BamWriter(const std::string& filename, const BamHeader& header, + const BamWriter::Config& config) + : BamWriter{filename, + header, + config.compressionLevel, + config.numThreads, + config.binCalculationMode, + config.useTempFile} +{ +} + +BamWriter::BamWriter(BamWriter&&) noexcept = default; + +BamWriter& BamWriter::operator=(BamWriter&&) noexcept = default; + +BamWriter::~BamWriter() +{ + const auto ret = bgzf_flush(d_->file_.get()->fp.bgzf); + UNUSED(ret); +} + +void BamWriter::TryFlush() +{ + // TODO: sanity checks on file_ & fp + const auto ret = bgzf_flush(d_->file_.get()->fp.bgzf); + if (ret != 0) throw std::runtime_error{"BamWriter: could not flush output buffer contents"}; +} + +void BamWriter::Write(const BamRecord& record) { d_->Write(record); } + +void BamWriter::Write(const BamRecord& record, int64_t* vOffset) { d_->Write(record, vOffset); } + +void BamWriter::Write(const BamRecordImpl& recordImpl) { d_->Write(recordImpl); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/BarcodeQuery.cpp b/src/BarcodeQuery.cpp new file mode 100644 index 0000000..ae95d1f --- /dev/null +++ b/src/BarcodeQuery.cpp @@ -0,0 +1,40 @@ +// File Description +/// \file BarcodeQuery.cpp +/// \brief Implements the BarcodeQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BarcodeQuery.h" + +#include + +#include "pbbam/CompositeBamReader.h" +#include "pbbam/PbiFilterTypes.h" + +namespace PacBio { +namespace BAM { + +class BarcodeQuery::BarcodeQueryPrivate +{ +public: + BarcodeQueryPrivate(const int16_t barcode, const DataSet& dataset) + : reader_{PbiBarcodeFilter{barcode}, dataset} + { + } + + PbiFilterCompositeBamReader reader_; // unsorted +}; + +BarcodeQuery::BarcodeQuery(const int16_t barcode, const DataSet& dataset) + : internal::IQuery(), d_{std::make_unique(barcode, dataset)} +{ +} + +BarcodeQuery::~BarcodeQuery() = default; + +bool BarcodeQuery::GetNext(BamRecord& r) { return d_->reader_.GetNext(r); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/BgzipFastaWriter.cpp b/src/BgzipFastaWriter.cpp new file mode 100644 index 0000000..a9df895 --- /dev/null +++ b/src/BgzipFastaWriter.cpp @@ -0,0 +1,53 @@ +// File Description +/// \file BgzipFastaWriter.cpp +/// \brief Implements the BgzipFastaWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BgzipFastaWriter.h" + +#include + +#include "pbbam/BamRecord.h" +#include "pbbam/FastqSequence.h" +#include "pbbam/FormatUtils.h" + +namespace PacBio { +namespace BAM { + +BgzipFastaWriter::BgzipFastaWriter(const std::string& fn) : IFastaWriter{}, writer_{fn} +{ + if (!FormatUtils::IsFastaFilename(fn)) { + throw std::runtime_error{"BgzipFastaWriter: filename '" + fn + + "' is not recognized as a FASTA file."}; + } +} + +BgzipFastaWriter::BgzipFastaWriter(const std::string& fn, const BgzipWriterConfig& config) + : IFastaWriter{}, writer_{fn, config} +{ + if (!FormatUtils::IsFastaFilename(fn)) { + throw std::runtime_error{"BgzipFastaWriter: filename '" + fn + + "' is not recognized as a FASTA file."}; + } +} + +void BgzipFastaWriter::TryFlush() {} + +void BgzipFastaWriter::Write(const BamRecordImpl& bam) { Write(bam.Name(), bam.Sequence()); } + +void BgzipFastaWriter::Write(const FastaSequence& fastq) { Write(fastq.Name(), fastq.Bases()); } + +void BgzipFastaWriter::Write(const BamRecord& bam) { Write(bam.FullName(), bam.Sequence()); } + +void BgzipFastaWriter::Write(const std::string& name, const std::string& bases) +{ + // TODO: wrap bases + std::string out{">" + name + '\n' + bases + '\n'}; + writer_.Write(out); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BgzipFastqWriter.cpp b/src/BgzipFastqWriter.cpp new file mode 100644 index 0000000..41744e5 --- /dev/null +++ b/src/BgzipFastqWriter.cpp @@ -0,0 +1,73 @@ +// File Description +/// \file BgzipFastqWriter.cpp +/// \brief Implements the BgzipFastqWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BgzipFastqWriter.h" + +#include + +#include "pbbam/BamRecord.h" +#include "pbbam/FastqSequence.h" +#include "pbbam/FormatUtils.h" + +namespace PacBio { +namespace BAM { + +BgzipFastqWriter::BgzipFastqWriter(const std::string& fn) : IFastqWriter{}, writer_{fn} +{ + if (!FormatUtils::IsFastqFilename(fn)) { + throw std::runtime_error{"BgzipFastqWriter: filename '" + fn + + "' is not recognized as a FASTQ file."}; + } +} + +BgzipFastqWriter::BgzipFastqWriter(const std::string& fn, const BgzipWriterConfig& config) + : IFastqWriter{}, writer_{fn, config} +{ + if (!FormatUtils::IsFastqFilename(fn)) { + throw std::runtime_error{"BgzipFastqWriter: filename '" + fn + + "' is not recognized as a FASTQ file."}; + } +} + +void BgzipFastqWriter::TryFlush() {} + +void BgzipFastqWriter::Write(const FastqSequence& fastq) +{ + Write(fastq.Name(), fastq.Bases(), fastq.Qualities()); +} + +void BgzipFastqWriter::Write(const BamRecord& bam) +{ + Write(bam.FullName(), bam.Sequence(), bam.Qualities()); +} + +void BgzipFastqWriter::Write(const BamRecordImpl& bam) +{ + Write(bam.Name(), bam.Sequence(), bam.Qualities()); +} + +void BgzipFastqWriter::Write(const std::string& name, const std::string& bases, + const Data::QualityValues& quals) +{ + Write(name, bases, quals.Fastq()); +} + +void BgzipFastqWriter::Write(const std::string& name, const std::string& bases, + const std::string& quals) +{ + std::string out{"@" + name + '\n' + bases + "\n+\n"}; + if (!quals.empty()) + out += quals; + else + out += std::string(bases.size(), '!'); + out.push_back('\n'); + writer_.Write(out); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/BgzipWriter.cpp b/src/BgzipWriter.cpp new file mode 100644 index 0000000..4429777 --- /dev/null +++ b/src/BgzipWriter.cpp @@ -0,0 +1,95 @@ +// File Description +/// \file BgzipWriter.cpp +/// \brief Implements the BgzipWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/BgzipWriter.h" + +#include +#include +#include +#include + +#include +#include + +#include "FileProducer.h" +#include "MemoryUtils.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "BgzipWriter(const BgzipWriter&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "BgzipWriter& operator=(const BgzipWriter&) is not = delete"); + +class BgzipWriter::BgzipWriterPrivate +{ +public: + BgzipWriterPrivate(std::string filename, + const BgzipWriterConfig& config = BgzipWriterConfig{}) // : filename_ + { + if (config.UseTempFile) fileProducer_ = std::make_unique(filename); + + // open file + usingFilename_ = (fileProducer_ ? fileProducer_->TempFilename() : filename); + const auto mode = + std::string("wb") + std::to_string(static_cast(config.CompressionLevel)); + bgzf_.reset(bgzf_open(usingFilename_.c_str(), mode.c_str())); + if (!bgzf_) { + throw std::runtime_error{"BgzipWriter: could not open file for writing: " + + usingFilename_}; + } + + // if no explicit thread count given, attempt built-in check + size_t actualNumThreads = config.NumThreads; + if (actualNumThreads == 0) { + actualNumThreads = std::thread::hardware_concurrency(); + + // if still unknown, default to single-threaded + if (actualNumThreads == 0) actualNumThreads = 1; + } + + // if multithreading requested, enable it + if (actualNumThreads > 1) bgzf_mt(bgzf_.get(), actualNumThreads, 256); + } + + size_t Write(const void* data, size_t numBytes) + { + const int written = bgzf_write(bgzf_.get(), data, numBytes); + if (written < 0) + throw std::runtime_error{"BgzipWriter: error writing to " + usingFilename_}; + return static_cast(written); + } + + std::string usingFilename_; + std::unique_ptr fileProducer_; + std::unique_ptr bgzf_; +}; + +BgzipWriter::BgzipWriter(std::string filename) + : d_{std::make_unique(std::move(filename))} +{ +} + +BgzipWriter::BgzipWriter(std::string filename, const BgzipWriterConfig& config) + : d_{std::make_unique(std::move(filename), config)} +{ +} + +BgzipWriter::BgzipWriter(BgzipWriter&&) noexcept = default; + +BgzipWriter& BgzipWriter::operator=(BgzipWriter&&) noexcept = default; + +BgzipWriter::~BgzipWriter() = default; + +size_t BgzipWriter::Write(const void* data, size_t numBytes) { return d_->Write(data, numBytes); } + +size_t BgzipWriter::Write(const std::string& data) { return d_->Write(data.c_str(), data.size()); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ChemistryTable.cpp b/src/ChemistryTable.cpp new file mode 100644 index 0000000..bebb5d5 --- /dev/null +++ b/src/ChemistryTable.cpp @@ -0,0 +1,179 @@ +// Author: Lance Hepler + +#include "PbbamInternalConfig.h" + +#include "ChemistryTable.h" + +#include +#include +#include + +#include "FileUtils.h" +#include "pbbam/exception/BundleChemistryMappingException.h" +#include "pugixml/pugixml.hpp" + +namespace PacBio { +namespace BAM { +namespace { + +ChemistryTable ChemistryTableFromXml(const std::string& mappingXml) +{ + if (!FileUtils::Exists(mappingXml)) + throw BundleChemistryMappingException{ + mappingXml, "SMRT_CHEMISTRY_BUNDLE_DIR defined but file not found"}; + + std::ifstream in(mappingXml); + pugi::xml_document doc; + const pugi::xml_parse_result loadResult = doc.load(in); + if (loadResult.status != pugi::status_ok) + throw BundleChemistryMappingException{ + mappingXml, "unparseable XML, error code:" + std::to_string(loadResult.status)}; + + // parse top-level attributes + pugi::xml_node rootNode = doc.document_element(); + if (rootNode == pugi::xml_node()) + throw BundleChemistryMappingException{mappingXml, "could not fetch XML root node"}; + + if (std::string(rootNode.name()) != "MappingTable") + throw BundleChemistryMappingException{mappingXml, "MappingTable not found"}; + + ChemistryTable table; + try { + for (const auto& childNode : rootNode) { + const std::string childName = childNode.name(); + if (childName != "Mapping") continue; + table.push_back({childNode.child("BindingKit").child_value(), + childNode.child("SequencingKit").child_value(), + childNode.child("SoftwareVersion").child_value(), + childNode.child("SequencingChemistry").child_value()}); + } + } catch (std::exception& e) { + const std::string msg = std::string{"Mapping entries unparseable - "} + e.what(); + throw BundleChemistryMappingException{mappingXml, msg}; + } + return table; +} + +} // namespace + +const ChemistryTable& BuiltInChemistryTable() +{ + // clang-format off + static ChemistryTable builtin{ + + // BindingKit, SequencingKit, BasecallerVersion, Chemistry + + // 3.0 ("Dromedary"): S/P1-C1/beta + {{"100-619-300", "100-620-000", "3.0", "S/P1-C1/beta"}}, + {{"100-619-300", "100-620-000", "3.1", "S/P1-C1/beta"}}, + + // 3.1 ("Echidna"): S/P1-C1.1 + {{"100-619-300", "100-867-300", "3.1", "S/P1-C1.1"}}, + {{"100-619-300", "100-867-300", "3.2", "S/P1-C1.1"}}, + {{"100-619-300", "100-867-300", "3.3", "S/P1-C1.1"}}, + + // 3.1.1 ("Flea"): S/P1-C1.2 + {{"100-619-300", "100-902-100", "3.1", "S/P1-C1.2"}}, + {{"100-619-300", "100-902-100", "3.2", "S/P1-C1.2"}}, + {{"100-619-300", "100-902-100", "3.3", "S/P1-C1.2"}}, + {{"100-619-300", "100-902-100", "4.0", "S/P1-C1.2"}}, + {{"100-619-300", "100-902-100", "4.1", "S/P1-C1.2"}}, + + // 3.2 ("Goat"): S/P1-C1.3 + {{"100-619-300", "100-972-200", "3.2", "S/P1-C1.3"}}, + {{"100-619-300", "100-972-200", "3.3", "S/P1-C1.3"}}, + {{"100-619-300", "100-972-200", "4.0", "S/P1-C1.3"}}, + {{"100-619-300", "100-972-200", "4.1", "S/P1-C1.3"}}, + + // 4.0 ("Seabiscuit"); S/P2-C2 + {{"100-862-200", "100-861-800", "4.0", "S/P2-C2"}}, + {{"100-862-200", "100-861-800", "4.1", "S/P2-C2"}}, + {{"100-862-200", "101-093-700", "4.1", "S/P2-C2"}}, + + // 5.0 ("Iguana"); S/P2-C2 + {{"100-862-200", "100-861-800", "5.0", "S/P2-C2/5.0"}}, + {{"100-862-200", "101-093-700", "5.0", "S/P2-C2/5.0"}}, + + // 5.0.1 ChemRel ("Sequel® Sequencing Plate Silwet"); S/P2-C2 + {{"100-862-200", "101-309-500", "5.0", "S/P2-C2/5.0"}}, + // 5.0.1 ChemRel ("Sequel® Sequencing Plate Silwet (4 rxn)"); S/P2-C2 + {{"100-862-200", "101-309-400", "5.0", "S/P2-C2/5.0"}}, + + // --- SG1/16509P/PA5.0 --- + // 2.1 binding kit/5.1PA support with .. + // 5.0 ("Iguana"); S/P2-C2 + {{"101-365-900", "100-861-800", "5.0", "S/P2-C2/5.0"}}, + {{"101-365-900", "101-093-700", "5.0", "S/P2-C2/5.0"}}, + + // 5.0.1 ChemRel; Sequel® Binding Kit 2.1; S/P2-C2 + {{"101-365-900", "101-309-500", "5.0", "S/P2-C2/5.0"}}, // Sequel® Sequencing Plate 2.1 Silwet (8 rxn) + {{"101-365-900", "101-309-400", "5.0", "S/P2-C2/5.0"}}, // Sequel® Sequencing Plate 2.1 Silwet (4 rxn) + + // 5.0.1 ChemRel; Sequel® Binding Kit 3.0; S/P3-C3 + {{"101-500-400", "101-427-500", "5.0", "S/P3-C3/5.0", "TAGT-415"}}, // Sequel® Sequencing Plate 3.0 (8 rxn) + {{"101-500-400", "101-427-800", "5.0", "S/P3-C3/5.0", "TAGT-415"}}, // Sequel® Sequencing Plate 3.0 (4 rxn) + + // 5.0.1 ChemRel; Sequel® Dev Binding Kit; S/P2-C2 + {{"101-490-800", "101-490-900", "5.0", "S/P3-C1/5.0-8M", "TAGT-416"}}, // Sequel II® Sequencing Plate (4 rxn) + {{"101-490-800", "101-491-000", "5.0", "S/P3-C1/5.0-8M", "TAGT-416"}}, // Sequel II® Sequencing Plate (8 rxn) + + // 5.0.1 ChemRel; Sequel® Sequencing Plate 3.1 for Dynamic Loading placeholder (4 rxn) + {{"101-500-400", "101-646-800", "5.0", "S/P3-C3/5.0", "TAGT-415"}}, // Sequel® Sequencing Plate 3.1 for Dynamic Loading placeholder + + // 5.0.1 ChemRel; Sequel® Dev Sequencing Plate Dyn Loading (4 rxn) + {{"101-490-800", "101-644-500", "5.0", "S/P3-C1/5.0-8M", "TAGT-418"}}, // Sequel® Dev Sequencing Plate Dyn Loading + + // 5.0.1 ChemRel; Sequel® Sequencing Plate Dyn Loading (4 rxn) + {{"101-490-800", "101-717-100", "5.0", "S/P3-C1/5.0-8M", "TAGT-418"}}, // Sequel® Dev Sequencing Plate Dyn Loading + + // 5.0.1 ChemRel; Sequel® Dev Sequencing Plate Dyn Loading (4 rxn) + {{"101-717-300", "101-644-500", "5.0", "S/P3-C1/5.0-8M", "TAGT-418"}}, // Sequel® Dev Sequencing Plate Dyn Loading + // 5.0.1 ChemRel; Sequel® Sequencing Plate Dyn Loading (4 rxn) + {{"101-717-300", "101-717-100", "5.0", "S/P3-C1/5.0-8M", "TAGT-418"}}, // Sequel® Dev Sequencing Plate Dyn Loading + + // 5.0.1 ChemRel; Sequel® Dev Sequencing Plate Dyn Loading (4 rxn) + {{"101-717-400", "101-644-500", "5.0", "S/P3-C1/5.0-8M", "TAGT-418"}}, // Sequel® Dev Sequencing Plate Dyn Loading + // 5.0.1 ChemRel; Sequel® Sequencing Plate Dyn Loading (4 rxn) + {{"101-717-400", "101-717-100", "5.0", "S/P3-C1/5.0-8M", "TAGT-418"}}, // Sequel® Dev Sequencing Plate Dyn Loading + + // Sequel® II Binding Kit 2.0; Sequel® II Sequencing Plate 2.0EA (4 Rxn) + {{"101-789-500", "101-789-300", "5.0", "S/P4-C2/5.0-8M", "TAGT-419"}}, + // Sequel® II Binding Kit 2.0; Sequel® II Sequencing Plate 2.0 (4 Rxn) + {{"101-789-500", "101-826-100", "5.0", "S/P4-C2/5.0-8M", "TAGT-420"}}, + // Sequel® II Binding Kit 2.0; Sequel® II Sequencing Plate 2.0 (4 Rxn) - QC + {{"101-789-500", "101-820-300", "5.0", "S/P4-C2/5.0-8M", "TAGT-420"}}, + + // Sequel® II Binding Kit 2.1; Sequel® II Sequencing Plate 2.0EA (4 Rxn) + {{"101-820-500", "101-789-300", "5.0", "S/P4.1-C2/5.0-8M", "TAGT-419"}}, + // Sequel® II Binding Kit 2.1; Sequel® II Sequencing Plate 2.0 (4 Rxn) + {{"101-820-500", "101-826-100", "5.0", "S/P4.1-C2/5.0-8M", "TAGT-420"}}, + // Sequel® II Binding Kit 2.1; Sequel® II Sequencing Plate 2.0 (4 Rxn) - QC + {{"101-820-500", "101-820-300", "5.0", "S/P4.1-C2/5.0-8M", "TAGT-420"}} + }; + // clang-format on + + return builtin; +} + +const ChemistryTable& GetChemistryTableFromEnv() +{ + static const ChemistryTable empty{}; + static std::map tableCache; + + std::string chemPath; + const char* pth = getenv("SMRT_CHEMISTRY_BUNDLE_DIR"); + if (pth != nullptr && pth[0] != '\0') + chemPath = pth; + else + return empty; + + auto it = tableCache.find(chemPath); + if (it != tableCache.end()) return it->second; + + auto tbl = ChemistryTableFromXml(chemPath + "/chemistry.xml"); + it = tableCache.emplace(std::move(chemPath), std::move(tbl)).first; + return it->second; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/ChemistryTable.h b/src/ChemistryTable.h new file mode 100644 index 0000000..18258af --- /dev/null +++ b/src/ChemistryTable.h @@ -0,0 +1,24 @@ +// Author: Lance Hepler + +#ifndef CHEMISTRYTABLE_H +#define CHEMISTRYTABLE_H + +#include "pbbam/Config.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { + +using ChemistryTable = std::vector>; + +const ChemistryTable& BuiltInChemistryTable(); + +const ChemistryTable& GetChemistryTableFromEnv(); + +} // namespace BAM +} // namespace PacBio + +#endif // CHEMISTRYTABLE_H diff --git a/src/Compare.cpp b/src/Compare.cpp new file mode 100644 index 0000000..f9149bc --- /dev/null +++ b/src/Compare.cpp @@ -0,0 +1,110 @@ +// File Description +/// \file Compare.cpp +/// \brief Implements the Compare class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/Compare.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { +namespace { + +struct TypeAlias +{ + std::string name_; + std::string op_; + std::string opAlpha_; + + TypeAlias(std::string name = std::string(), std::string op = std::string(), + std::string opAlpha = std::string()) + : name_(std::move(name)), op_(std::move(op)), opAlpha_(std::move(opAlpha)) + { + } +}; + +struct CompareTypeHash +{ + size_t operator()(const Compare::Type& t) const + { + return std::hash()(static_cast(t)); + } +}; + +// clang-format off +static const std::unordered_map opToTypeMap = +{ + // basic operators plus some permissiveness for other representations + { "==", Compare::EQUAL }, + { "=", Compare::EQUAL }, + { "eq", Compare::EQUAL }, + { "in", Compare::EQUAL }, + { "!=", Compare::NOT_EQUAL }, + { "ne", Compare::NOT_EQUAL }, + { "not_in", Compare::NOT_EQUAL }, + { "<", Compare::LESS_THAN }, + { "lt", Compare::LESS_THAN }, + { "<", Compare::LESS_THAN }, + { "<=", Compare::LESS_THAN_EQUAL }, + { "lte", Compare::LESS_THAN_EQUAL }, + { "<=", Compare::LESS_THAN_EQUAL }, + { ">", Compare::GREATER_THAN }, + { "gt", Compare::GREATER_THAN }, + { ">", Compare::GREATER_THAN }, + { ">=", Compare::GREATER_THAN_EQUAL }, + { "gte", Compare::GREATER_THAN_EQUAL }, + { ">=", Compare::GREATER_THAN_EQUAL }, + { "&", Compare::CONTAINS }, + { "~", Compare::NOT_CONTAINS } +}; + +static const std::unordered_map typeAliases = +{ + { Compare::EQUAL, TypeAlias{ "Compare::EQUAL", "==", "eq" } }, + { Compare::NOT_EQUAL, TypeAlias{ "Compare::NOT_EQUAL", "!=", "ne" } }, + { Compare::LESS_THAN, TypeAlias{ "Compare::LESS_THAN", "<", "lt" } }, + { Compare::LESS_THAN_EQUAL, TypeAlias{ "Compare::LESS_THAN_EQUAL", "<=", "lte" } }, + { Compare::GREATER_THAN, TypeAlias{ "Compare::GREATER_THAN", ">", "gt" } }, + { Compare::GREATER_THAN_EQUAL, TypeAlias{ "Compare::GREATER_THAN_EQUAL", ">=", "gte" } }, + { Compare::CONTAINS, TypeAlias{ "Compare::CONTAINS", "&", "and" } }, + { Compare::NOT_CONTAINS, TypeAlias{ "Compare::NOT_CONTAINS", "~", "not" } } +}; +// clang-format on + +} // anonymous + +Compare::Type Compare::TypeFromOperator(const std::string& opString) +{ + try { + return opToTypeMap.at(opString); + } catch (std::exception&) { + throw std::runtime_error{"Compare: " + opString + " is not a valid comparison operator."}; + } +} + +std::string Compare::TypeToName(const Compare::Type& type) +{ + try { + return typeAliases.at(type).name_; + } catch (std::exception&) { + throw std::runtime_error{"Compare: invalid comparison type encountered"}; + } +} + +std::string Compare::TypeToOperator(const Compare::Type& type, bool asAlpha) +{ + try { + return asAlpha ? typeAliases.at(type).opAlpha_ : typeAliases.at(type).op_; + } catch (std::exception&) { + throw std::runtime_error{"Compare: invalid comparison type encountered"}; + } +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/CompositeFastaReader.cpp b/src/CompositeFastaReader.cpp new file mode 100644 index 0000000..a53daaf --- /dev/null +++ b/src/CompositeFastaReader.cpp @@ -0,0 +1,42 @@ +// File Description +/// \file BamRecordView.cpp +/// \brief Implements the BamRecordTags utility class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/CompositeFastaReader.h" + +namespace PacBio { +namespace BAM { + +CompositeFastaReader::CompositeFastaReader(const std::vector& fastaFiles) +{ + for (const auto& fn : fastaFiles) + readers_.emplace_back(std::make_unique(fn)); +} + +CompositeFastaReader::CompositeFastaReader(const DataSet& dataset) + : CompositeFastaReader{dataset.FastaFiles()} +{ +} + +bool CompositeFastaReader::GetNext(FastaSequence& seq) +{ + // try first reader, if successful return true + // else pop reader and try next, until all readers exhausted + while (!readers_.empty()) { + auto& reader = readers_.front(); + if (reader->GetNext(seq)) + return true; + else + readers_.pop_front(); + } + + // no readers available + return false; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/Config.cpp b/src/Config.cpp new file mode 100644 index 0000000..2fd4820 --- /dev/null +++ b/src/Config.cpp @@ -0,0 +1,58 @@ +// File Description +/// \file Config.cpp +/// \brief Initializes global variable defaults. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/Config.h" + +#include +#include +#include + +#include +#include + +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { + +// Initialized to -1 to indicate default. We will set this to HTS_LOG_OFF unless +// client code overrides. This keeps htslib from polluting stdout/stderr on its own. +// +int HtslibVerbosity = -1; + +bool DoesHtslibSupportLongCigar() +{ + const std::string htsVersion = hts_version(); + + // remove any "-" for non-release versions + const auto versionBase = PacBio::BAM::Split(htsVersion, '-'); + if (versionBase.empty()) + throw std::runtime_error{"invalid htslib version format: " + htsVersion}; + + // grab major/minor version numbers + const auto versionParts = PacBio::BAM::Split(versionBase[0], '.'); + if (versionParts.size() < 2) + throw std::runtime_error{"invalid htslib version format: " + htsVersion}; + + // check against v1.7 + const int versionMajor = std::stoi(versionParts[0]); + const int versionMinor = std::stoi(versionParts[1]); + static constexpr const int v17_major = 1; + static constexpr const int v17_minor = 7; + return std::tie(versionMajor, versionMinor) >= std::tie(v17_major, v17_minor); +} + +#ifdef PBBAM_PERMISSIVE_CIGAR +static const bool PermissiveCigar = []() { + Data::CigarOperation::DisableAutoValidation(); + return true; +}(); +#endif // PBBAM_PERMISSIVE_CIGAR + +} // namespace BAM +} // namespace PacBio diff --git a/src/DataSet.cpp b/src/DataSet.cpp new file mode 100644 index 0000000..e6f4f89 --- /dev/null +++ b/src/DataSet.cpp @@ -0,0 +1,620 @@ +// File Description +/// \file DataSet.cpp +/// \brief Implements the DataSet class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/DataSet.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "DataSetIO.h" +#include "DataSetUtils.h" +#include "FileUtils.h" +#include "TimeUtils.h" + +#include "pbbam/internal/DataSetBaseTypes.h" + +namespace PacBio { +namespace BAM { +namespace { + +const std::string defaultVersion{"4.0.0"}; + +void GetAllFiles(const ExternalResources& resources, std::vector* result) +{ + for (const auto& resource : resources) { + + // store this resource's path + result->push_back(resource.ResourceId()); + + // store any child indices + for (const auto& idx : resource.FileIndices()) + result->push_back(idx.ResourceId()); + + // recurse into any other child resources + GetAllFiles(resource.ExternalResources(), result); + } +} + +} // namespace + +using internal::DataSetElement; + +DataSet::DataSet() : DataSet(DataSet::GENERIC) {} + +DataSet::DataSet(const DataSet::TypeEnum type) +{ + switch (type) { + case DataSet::GENERIC: + d_ = std::make_unique(); + break; + case DataSet::ALIGNMENT: + d_ = std::make_unique(); + break; + case DataSet::BARCODE: + d_ = std::make_unique(); + break; + case DataSet::CONSENSUS_ALIGNMENT: + d_ = std::make_unique(); + break; + case DataSet::CONSENSUS_READ: + d_ = std::make_unique(); + break; + case DataSet::CONTIG: + d_ = std::make_unique(); + break; + case DataSet::HDF_SUBREAD: + d_ = std::make_unique(); + break; + case DataSet::REFERENCE: + d_ = std::make_unique(); + break; + case DataSet::SUBREAD: + d_ = std::make_unique(); + break; + case DataSet::TRANSCRIPT: + d_ = std::make_unique(); + break; + case DataSet::TRANSCRIPT_ALIGNMENT: + d_ = std::make_unique(); + break; + default: + throw std::runtime_error{"DataSet: unsupported type"}; + } + + d_->Path(FileUtils::CurrentWorkingDirectory()); +} + +DataSet::DataSet(const BamFile& bamFile) : d_(DataSetIO::FromUri(bamFile.Filename())) +{ + d_->Path(FileUtils::CurrentWorkingDirectory()); +} + +DataSet::DataSet(const std::string& filename) : d_(DataSetIO::FromUri(filename)) +{ + // for FOFN contents and raw BAM filenames, we can just use the current + // directory as the starting path. + // + // (any relative paths in the FOFN have already been resolved) + // + if (boost::algorithm::iends_with(filename, ".fofn") || + boost::algorithm::iends_with(filename, ".bam") || + boost::algorithm::iends_with(filename, ".fasta") || + boost::algorithm::iends_with(filename, ".fa")) { + d_->Path(FileUtils::CurrentWorkingDirectory()); + } + + else { + if (boost::algorithm::iends_with(filename, ".xml")) d_->FromInputXml(true); + d_->Path(FileUtils::DirectoryName(filename)); + } +} + +DataSet::DataSet(const std::vector& filenames) : d_(DataSetIO::FromUris(filenames)) +{ + d_->Path(FileUtils::CurrentWorkingDirectory()); +} + +DataSet::DataSet(const DataSet& other) +{ + const bool otherFromXml = other.d_->FromInputXml(); + std::ostringstream out; + DataSetIO::ToStream(other.d_, out); + const std::string xml = out.str(); + d_ = DataSetIO::FromXmlString(xml); + d_->Path(other.d_->Path()); + d_->FromInputXml(otherFromXml); +} + +DataSet& DataSet::operator=(const DataSet& other) +{ + if (this != &other) *this = DataSet{other}; + return *this; +} + +DataSet& DataSet::operator+=(const DataSet& other) +{ + *d_.get() += *other.d_.get(); + return *this; +} + +std::vector DataSet::AllFiles() const +{ + // get all files + std::vector result; + GetAllFiles(ExternalResources(), &result); + + // resolve relative paths + std::transform(result.begin(), result.end(), result.begin(), + [this](const std::string& fn) { return this->ResolvePath(fn); }); + return result; +} + +const std::string& DataSet::Attribute(const std::string& name) const { return d_->Attribute(name); } + +std::string& DataSet::Attribute(const std::string& name) { return d_->Attribute(name); } + +DataSet& DataSet::Attribute(const std::string& name, const std::string& value) +{ + d_->Attribute(name, value); + return *this; +} + +std::vector DataSet::BamFiles() const +{ + std::vector result; + std::vector fns = BamFilenames(); + result.reserve(fns.size()); + + for (const auto& fn : fns) { + result.emplace_back(fn); + } + return result; +} + +std::vector DataSet::BamFilenames() const +{ + std::vector result; + const PacBio::BAM::ExternalResources& resources = ExternalResources(); + + result.reserve(resources.Size()); + for (const ExternalResource& ext : resources) { + + // only bother resolving file path if this is a BAM file + boost::iterator_range bamFound = + boost::algorithm::ifind_first(ext.MetaType(), "bam"); + if (!bamFound.empty()) { + const std::string fn = ResolvePath(ext.ResourceId()); + result.emplace_back(fn); + } + } + return result; +} + +const std::string& DataSet::CreatedAt() const { return d_->CreatedAt(); } + +std::string& DataSet::CreatedAt() { return d_->CreatedAt(); } + +DataSet& DataSet::CreatedAt(const std::string& createdAt) +{ + d_->CreatedAt(createdAt); + return *this; +} + +const PacBio::BAM::Extensions& DataSet::Extensions() const { return d_->Extensions(); } + +PacBio::BAM::Extensions& DataSet::Extensions() { return d_->Extensions(); } + +DataSet& DataSet::Extensions(const PacBio::BAM::Extensions& extensions) +{ + d_->Extensions(extensions); + return *this; +} + +const PacBio::BAM::ExternalResources& DataSet::ExternalResources() const +{ + return d_->ExternalResources(); +} + +PacBio::BAM::ExternalResources& DataSet::ExternalResources() { return d_->ExternalResources(); } + +DataSet& DataSet::ExternalResources(const PacBio::BAM::ExternalResources& resources) +{ + d_->ExternalResources(resources); + return *this; +} + +std::vector DataSet::FastaFiles() const +{ + const PacBio::BAM::ExternalResources& resources = ExternalResources(); + + std::vector result; + result.reserve(resources.Size()); + for (const ExternalResource& ext : resources) { + + // only bother resolving file path if this is a BAM file + boost::iterator_range fastaFound = + boost::algorithm::ifind_first(ext.MetaType(), "fasta"); + if (!fastaFound.empty()) { + const std::string fn = ResolvePath(ext.ResourceId()); + result.push_back(fn); + } + } + return result; +} + +const PacBio::BAM::Filters& DataSet::Filters() const { return d_->Filters(); } + +PacBio::BAM::Filters& DataSet::Filters() { return d_->Filters(); } + +DataSet& DataSet::Filters(const PacBio::BAM::Filters& filters) +{ + d_->Filters(filters); + return *this; +} + +const std::string& DataSet::Format() const { return d_->Format(); } + +std::string& DataSet::Format() { return d_->Format(); } + +DataSet& DataSet::Format(const std::string& format) +{ + d_->Format(format); + return *this; +} + +DataSet DataSet::FromXml(const std::string& xml) +{ + DataSet result; + result.d_ = DataSetIO::FromXmlString(xml); + result.d_->Path(FileUtils::DirectoryName(xml)); + result.d_->FromInputXml(true); + return result; +} + +std::vector DataSet::GenomicIntervals() const +{ + // need to gather the contig lengths + std::map contigLengths; + for (const BamFile& b : BamFiles()) { + const BamHeader& header = b.Header(); + const int32_t numContigs = header.NumSequences(); + for (int32_t i = 0; i < numContigs; ++i) { + const std::string refName = header.SequenceName(i); + const int32_t refLength = boost::lexical_cast(header.SequenceLength(i)); + + const auto it = contigLengths.find(refName); + if (it == contigLengths.cend()) + contigLengths.emplace(refName, refLength); + else if (it->second != refLength) { + throw std::runtime_error{ + "DataSet: " + refName + " occurs twice with different lengths ('" + + std::to_string(it->second) + "' and '" + std::to_string(refLength) + "')"}; + } + } + } + + // with the lengths of all contigs known, we can build + // the minimal interval set induced by the filters + using intT = boost::icl::interval_set; + using intInterval = intT::interval_type; + + std::map contigIntervals; + int32_t numFilters = 0; + + for (const auto& xmlFilter : Filters()) { + ++numFilters; + boost::optional contigName; + + intT intersectedInterval{intInterval{0, std::numeric_limits::max()}}; + + for (const auto& xmlProperty : xmlFilter.Properties()) { + const std::string XmlName = xmlProperty.Name(); + const std::string XmlOperator = xmlProperty.Operator(); + const std::string XmlValue = xmlProperty.Value(); + + if ("rname" == XmlName) { + if ("=" == XmlOperator) { + contigName = XmlValue; + + const auto it = contigLengths.find(XmlValue); + if (it == contigLengths.cend()) + throw std::runtime_error{"DataSet: Could not find contig '" + XmlValue + + "' in BAM files"}; + else + intersectedInterval &= intInterval(0, it->second); + } else + throw std::runtime_error{ + "DatSet: '" + XmlOperator + + "' is an unrecognized property operator, only '=' is recognized"}; + } else if ("tstart" == XmlName) { + if ((XmlOperator != "<") && (XmlOperator != "<=")) + throw std::runtime_error{ + "DataSet: tstart only supports '<' and '<=' operators"}; + + const int32_t end = boost::lexical_cast(XmlValue) + ("<=" == XmlOperator); + intersectedInterval &= intInterval(0, end); + } else if ("tend" == XmlName) { + if ((XmlOperator != ">") && (XmlOperator != ">=")) + throw std::runtime_error{"DataSet: tend only supports '>' and '>=' operators"}; + + const int32_t start = + boost::lexical_cast(XmlValue) - (">=" == XmlOperator); + intersectedInterval &= intInterval(start, std::numeric_limits::max()); + } else + throw std::runtime_error{"DataSet: '" + XmlName + + "' is an unrecognized filter property name"}; + } + + if (contigName) + contigIntervals[contigName.value()] |= intersectedInterval; + else + throw std::runtime_error{ + "DataSet: current filter does not have a valid 'rname' attribute"}; + } + + // extract all GenomicIntervals + std::vector result; + if (numFilters) { + // have some filters, only return regions passing filters + for (const auto& contigs : contigIntervals) { + const std::string& contigName = contigs.first; + for (const auto& i : contigs.second) { + // don't append empty intervals to the result + if (boost::icl::length(i)) result.emplace_back(contigName, i.lower(), i.upper()); + } + } + } else { + // no filters, return complete list of intervals + for (const auto& contigs : contigLengths) + result.emplace_back(contigs.first, 0, contigs.second); + } + + return result; +} + +const PacBio::BAM::DataSetMetadata& DataSet::Metadata() const { return d_->Metadata(); } + +PacBio::BAM::DataSetMetadata& DataSet::Metadata() { return d_->Metadata(); } + +DataSet& DataSet::Metadata(const PacBio::BAM::DataSetMetadata& metadata) +{ + d_->Metadata(metadata); + return *this; +} + +const std::string& DataSet::MetaType() const { return d_->MetaType(); } + +std::string& DataSet::MetaType() { return d_->MetaType(); } + +DataSet& DataSet::MetaType(const std::string& metatype) +{ + d_->MetaType(metatype); + return *this; +} + +const std::string& DataSet::ModifiedAt() const { return d_->ModifiedAt(); } + +std::string& DataSet::ModifiedAt() { return d_->ModifiedAt(); } + +DataSet& DataSet::ModifiedAt(const std::string& modifiedAt) +{ + d_->ModifiedAt(modifiedAt); + return *this; +} + +const std::string& DataSet::Name() const { return d_->Name(); } + +std::string& DataSet::Name() { return d_->Name(); } + +DataSet& DataSet::Name(const std::string& name) +{ + d_->Name(name); + return *this; +} + +const NamespaceRegistry& DataSet::Namespaces() const { return d_->Namespaces(); } + +NamespaceRegistry& DataSet::Namespaces() { return d_->Namespaces(); } + +DataSet::TypeEnum DataSet::NameToType(const std::string& typeName) +{ + static std::unordered_map lookup; + if (lookup.empty()) { + lookup["DataSet"] = DataSet::GENERIC; + lookup["AlignmentSet"] = DataSet::ALIGNMENT; + lookup["BarcodeSet"] = DataSet::BARCODE; + lookup["ConsensusAlignmentSet"] = DataSet::CONSENSUS_ALIGNMENT; + lookup["ConsensusReadSet"] = DataSet::CONSENSUS_READ; + lookup["ContigSet"] = DataSet::CONTIG; + lookup["HdfSubreadSet"] = DataSet::HDF_SUBREAD; + lookup["ReferenceSet"] = DataSet::REFERENCE; + lookup["SubreadSet"] = DataSet::SUBREAD; + lookup["TranscriptSet"] = DataSet::TRANSCRIPT; + lookup["TranscriptAlignmentSet"] = DataSet::TRANSCRIPT_ALIGNMENT; + } + return lookup.at(typeName); // throws if unknown typename +} + +const std::string& DataSet::Path() const { return d_->Path(); } + +std::vector DataSet::ResolvedResourceIds() const +{ + const PacBio::BAM::ExternalResources& resources = ExternalResources(); + + std::vector result; + result.reserve(resources.Size()); + for (const ExternalResource& ext : resources) { + result.push_back(ResolvePath(ext.ResourceId())); + } + return result; +} + +std::string DataSet::ResolvePath(const std::string& originalPath) const +{ + return FileUtils::ResolvedFilePath(originalPath, d_->Path()); +} + +const std::string& DataSet::ResourceId() const { return d_->ResourceId(); } + +std::string& DataSet::ResourceId() { return d_->ResourceId(); } + +DataSet& DataSet::ResourceId(const std::string& resourceId) +{ + d_->ResourceId(resourceId); + return *this; +} + +void DataSet::Save(const std::string& outputFilename) const +{ + DataSetIO::ToFile(d_, outputFilename); +} + +void DataSet::SaveToStream(std::ostream& out) const { DataSetIO::ToStream(d_, out); } + +std::set DataSet::SequencingChemistries() const +{ + const std::vector bamFiles{BamFiles()}; + + std::set result; + for (const BamFile& bf : bamFiles) { + if (!bf.IsPacBioBAM()) + throw std::runtime_error{ + "DataSet: only PacBio BAMs are supported for fetching chemistry info"}; + const std::vector readGroups{bf.Header().ReadGroups()}; + for (const ReadGroupInfo& rg : readGroups) + result.insert(rg.SequencingChemistry()); + } + return result; +} + +const PacBio::BAM::SubDataSets& DataSet::SubDataSets() const { return d_->SubDataSets(); } + +PacBio::BAM::SubDataSets& DataSet::SubDataSets() { return d_->SubDataSets(); } + +DataSet& DataSet::SubDataSets(const PacBio::BAM::SubDataSets& subdatasets) +{ + d_->SubDataSets(subdatasets); + return *this; +} + +const std::string& DataSet::Tags() const { return d_->Tags(); } + +std::string& DataSet::Tags() { return d_->Tags(); } + +DataSet& DataSet::Tags(const std::string& tags) +{ + d_->Tags(tags); + return *this; +} + +const std::string& DataSet::TimeStampedName() const { return d_->TimeStampedName(); } + +std::string& DataSet::TimeStampedName() { return d_->TimeStampedName(); } + +DataSet& DataSet::TimeStampedName(const std::string& timeStampedName) +{ + d_->TimeStampedName(timeStampedName); + return *this; +} + +PacBio::BAM::DataSet::TypeEnum DataSet::Type() const { return DataSet::NameToType(TypeName()); } + +DataSet& DataSet::Type(const DataSet::TypeEnum type) +{ + d_->Label(DataSet::TypeToName(type)); + return *this; +} + +std::string DataSet::TypeName() const { return d_->LocalNameLabel().to_string(); } + +std::string DataSet::TypeToName(const DataSet::TypeEnum& type) +{ + switch (type) { + case DataSet::GENERIC: + return "DataSet"; + case DataSet::ALIGNMENT: + return "AlignmentSet"; + case DataSet::BARCODE: + return "BarcodeSet"; + case DataSet::CONSENSUS_ALIGNMENT: + return "ConsensusAlignmentSet"; + case DataSet::CONSENSUS_READ: + return "ConsensusReadSet"; + case DataSet::CONTIG: + return "ContigSet"; + case DataSet::HDF_SUBREAD: + return "HdfSubreadSet"; + case DataSet::REFERENCE: + return "ReferenceSet"; + case DataSet::SUBREAD: + return "SubreadSet"; + case DataSet::TRANSCRIPT: + return "TranscriptSet"; + case DataSet::TRANSCRIPT_ALIGNMENT: + return "TranscriptAlignmentSet"; + default: + throw std::runtime_error{"DataSet: unsupported dataset type"}; + } +} + +const std::string& DataSet::UniqueId() const { return d_->UniqueId(); } + +std::string& DataSet::UniqueId() { return d_->UniqueId(); } + +DataSet& DataSet::UniqueId(const std::string& uuid) +{ + d_->UniqueId(uuid); + return *this; +} + +const std::string& DataSet::Version() const { return d_->Version(); } + +std::string& DataSet::Version() { return d_->Version(); } + +DataSet& DataSet::Version(const std::string& version) +{ + d_->Version(version); + return *this; +} + +// Exposed timestamp utils + +std::string CurrentTimestamp() { return TimeUtils::ToDataSetFormat(TimeUtils::CurrentTime()); } + +std::string ToDataSetFormat(const std::chrono::system_clock::time_point& tp) +{ + return TimeUtils::ToDataSetFormat(tp); +} + +std::string ToDataSetFormat(const time_t& t) +{ + return TimeUtils::ToDataSetFormat(std::chrono::system_clock::from_time_t(t)); +} + +std::string ToIso8601(const std::chrono::system_clock::time_point& tp) +{ + return TimeUtils::ToIso8601(tp); +} + +std::string ToIso8601(const time_t& t) +{ + return TimeUtils::ToIso8601(std::chrono::system_clock::from_time_t(t)); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/DataSetBaseTypes.cpp b/src/DataSetBaseTypes.cpp new file mode 100644 index 0000000..63a820b --- /dev/null +++ b/src/DataSetBaseTypes.cpp @@ -0,0 +1,322 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/internal/DataSetBaseTypes.h" + +#include + +#include + +#include "DataSetUtils.h" +#include "TimeUtils.h" +#include "pbbam/DataSetTypes.h" +#include "pbbam/Unused.h" + +namespace PacBio { +namespace BAM { +namespace internal { + +// ---------------- +// BaseEntityType +// ---------------- + +BaseEntityType::BaseEntityType(const std::string& label, const XsdType& xsd) + : DataSetElement(label, xsd) +{ + if (CreatedAt().empty()) CreatedAt(TimeUtils::ToIso8601(TimeUtils::CurrentTime())); + if (Version().empty()) Version(XML_VERSION); +} + +BaseEntityType::BaseEntityType(const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd) + : DataSetElement(label, fromInputXml, xsd) +{ +} + +const std::string& BaseEntityType::CreatedAt() const { return Attribute("CreatedAt"); } + +std::string& BaseEntityType::CreatedAt() { return Attribute("CreatedAt"); } + +BaseEntityType& BaseEntityType::CreatedAt(const std::string& createdAt) +{ + Attribute("CreatedAt", createdAt); + return *this; +} + +const std::string& BaseEntityType::Description() const { return Attribute("Description"); } + +std::string& BaseEntityType::Description() { return Attribute("Description"); } + +BaseEntityType& BaseEntityType::Description(const std::string& description) +{ + Attribute("Description", description); + return *this; +} + +DEFINE_ACCESSORS(BaseEntityType, Extensions, Extensions) + +BaseEntityType& BaseEntityType::Extensions(const PacBio::BAM::Extensions& extensions) +{ + Extensions() = extensions; + return *this; +} + +const std::string& BaseEntityType::Format() const { return Attribute("Format"); } + +std::string& BaseEntityType::Format() { return Attribute("Format"); } + +BaseEntityType& BaseEntityType::Format(const std::string& format) +{ + Attribute("Format", format); + return *this; +} + +const std::string& BaseEntityType::ModifiedAt() const { return Attribute("ModifiedAt"); } + +std::string& BaseEntityType::ModifiedAt() { return Attribute("ModifiedAt"); } + +BaseEntityType& BaseEntityType::ModifiedAt(const std::string& modifiedAt) +{ + Attribute("ModifiedAt", modifiedAt); + return *this; +} + +const std::string& BaseEntityType::Name() const { return Attribute("Name"); } + +std::string& BaseEntityType::Name() { return Attribute("Name"); } + +BaseEntityType& BaseEntityType::Name(const std::string& name) +{ + Attribute("Name", name); + return *this; +} + +const std::string& BaseEntityType::ResourceId() const { return Attribute("ResourceId"); } + +std::string& BaseEntityType::ResourceId() { return Attribute("ResourceId"); } + +BaseEntityType& BaseEntityType::ResourceId(const std::string& resourceId) +{ + Attribute("ResourceId", resourceId); + return *this; +} + +const std::string& BaseEntityType::Tags() const { return Attribute("Tags"); } + +std::string& BaseEntityType::Tags() { return Attribute("Tags"); } + +BaseEntityType& BaseEntityType::Tags(const std::string& tags) +{ + Attribute("Tags", tags); + return *this; +} + +const std::string& BaseEntityType::Version() const { return Attribute("Version"); } + +std::string& BaseEntityType::Version() { return Attribute("Version"); } + +BaseEntityType& BaseEntityType::Version(const std::string& version) +{ + Attribute("Version", version); + return *this; +} + +// ---------------- +// DataEntityType +// ---------------- + +DataEntityType::DataEntityType(const std::string& label, const XsdType& xsd) + : BaseEntityType(label, xsd) +{ +} + +DataEntityType::DataEntityType(const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd) + : BaseEntityType(label, fromInputXml, xsd) +{ +} + +const std::string& DataEntityType::Checksum() const { return ChildText("Checksum"); } + +std::string& DataEntityType::Checksum() { return ChildText("Checksum"); } + +DataEntityType& DataEntityType::Checksum(const std::string& checksum) +{ + ChildText("Checksum", checksum); + return *this; +} + +const std::string& DataEntityType::EncodedValue() const { return ChildText("EncodedValue"); } + +std::string& DataEntityType::EncodedValue() { return ChildText("EncodedValue"); } + +DataEntityType& DataEntityType::EncodedValue(const std::string& encodedValue) +{ + ChildText("EncodedValue", encodedValue); + return *this; +} + +const std::string& DataEntityType::MetaType() const { return Attribute("MetaType"); } + +std::string& DataEntityType::MetaType() { return Attribute("MetaType"); } + +DataEntityType& DataEntityType::MetaType(const std::string& metatype) +{ + Attribute("MetaType", metatype); + return *this; +} + +const std::string& DataEntityType::SimpleValue() const { return Attribute("SimpleValue"); } + +std::string& DataEntityType::SimpleValue() { return Attribute("SimpleValue"); } + +DataEntityType& DataEntityType::SimpleValue(const std::string& simpleValue) +{ + Attribute("SimpleValue", simpleValue); + return *this; +} + +const std::string& DataEntityType::TimeStampedName() const { return Attribute("TimeStampedName"); } + +std::string& DataEntityType::TimeStampedName() { return Attribute("TimeStampedName"); } + +DataEntityType& DataEntityType::TimeStampedName(const std::string& timeStampedName) +{ + Attribute("TimeStampedName", timeStampedName); + return *this; +} + +const std::string& DataEntityType::UniqueId() const { return Attribute("UniqueId"); } + +std::string& DataEntityType::UniqueId() { return Attribute("UniqueId"); } + +DataEntityType& DataEntityType::UniqueId(const std::string& uuid) +{ + Attribute("UniqueId", uuid); + return *this; +} + +const std::string& DataEntityType::ValueDataType() const { return Attribute("ValueDataType"); } + +std::string& DataEntityType::ValueDataType() { return Attribute("ValueDataType"); } + +DataEntityType& DataEntityType::ValueDataType(const std::string& valueDataType) +{ + Attribute("ValueDataType", valueDataType); + return *this; +} + +// ----------------- +// IndexedDataType +// ----------------- + +IndexedDataType::IndexedDataType(const std::string& metatype, const std::string& filename, + const std::string& label, const XsdType& xsd) + : InputOutputDataType(metatype, filename, label, xsd) +{ +} + +IndexedDataType::IndexedDataType(const std::string& metatype, const std::string& filename, + const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd) + : InputOutputDataType(metatype, filename, label, fromInputXml, xsd) +{ +} + +DEFINE_ACCESSORS(IndexedDataType, FileIndices, FileIndices) + +IndexedDataType& IndexedDataType::FileIndices(const PacBio::BAM::FileIndices& indices) +{ + FileIndices() = indices; + return *this; +} + +// --------------------- +// InputOutputDataType +// --------------------- + +InputOutputDataType::InputOutputDataType(const std::string& metatype, const std::string& filename, + const std::string& label, const XsdType& xsd) + : StrictEntityType(metatype, label, xsd) +{ + ResourceId(filename); +} + +InputOutputDataType::InputOutputDataType(const std::string& metatype, const std::string& filename, + const std::string& label, const FromInputXml& fromInputXml, + const XsdType& xsd) + : StrictEntityType(metatype, label, fromInputXml, xsd) +{ + ResourceId(filename); +} + +// ---------------- +// StrictEntityType +// ---------------- + +StrictEntityType::StrictEntityType(const std::string& metatype, const std::string& label, + const XsdType& xsd) + : BaseEntityType(label, xsd) +{ + // MetaType + MetaType(metatype); + + // TimeStampedName + const size_t numChars = metatype.size(); + std::string transformedMetatype; + transformedMetatype.resize(numChars); + for (size_t i = 0; i < numChars; ++i) { + const char c = metatype.at(i); + transformedMetatype[i] = ((c == '.') ? '_' : tolower(c)); + } + const std::string tsn = + transformedMetatype + "-" + TimeUtils::ToDataSetFormat(TimeUtils::CurrentTime()); + TimeStampedName(tsn); + + // UniqueId + UniqueId(GenerateUuid()); +} + +StrictEntityType::StrictEntityType(const std::string& /*metatype*/, const std::string& label, + const FromInputXml& fromInputXml, const XsdType& xsd) + : BaseEntityType(label, fromInputXml, xsd) +{ +} + +const std::string& StrictEntityType::MetaType() const { return Attribute("MetaType"); } + +std::string& StrictEntityType::MetaType() { return Attribute("MetaType"); } + +StrictEntityType& StrictEntityType::MetaType(const std::string& metatype) +{ + Attribute("MetaType", metatype); + return *this; +} + +const std::string& StrictEntityType::TimeStampedName() const +{ + return Attribute("TimeStampedName"); +} + +std::string& StrictEntityType::TimeStampedName() { return Attribute("TimeStampedName"); } + +StrictEntityType& StrictEntityType::TimeStampedName(const std::string& timeStampedName) +{ + Attribute("TimeStampedName", timeStampedName); + return *this; +} + +const std::string& StrictEntityType::UniqueId() const { return Attribute("UniqueId"); } + +std::string& StrictEntityType::UniqueId() { return Attribute("UniqueId"); } + +StrictEntityType& StrictEntityType::UniqueId(const std::string& uuid) +{ + Attribute("UniqueId", uuid); + return *this; +} + +} // namespace internal +} // namespace BAM +} // namespace PacBio diff --git a/src/DataSetElement.cpp b/src/DataSetElement.cpp new file mode 100644 index 0000000..fa8ee67 --- /dev/null +++ b/src/DataSetElement.cpp @@ -0,0 +1,20 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/internal/DataSetElement.h" + +#include "DataSetUtils.h" + +namespace PacBio { +namespace BAM { +namespace internal { + +const std::string& DataSetElement::SharedNullString() +{ + return internal::NullObject(); +} + +} // namespace internal +} // namespace BAM +} // namespace PacBio diff --git a/src/DataSetIO.cpp b/src/DataSetIO.cpp new file mode 100644 index 0000000..ad3d1a0 --- /dev/null +++ b/src/DataSetIO.cpp @@ -0,0 +1,156 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "DataSetIO.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "FileUtils.h" +#include "FofnReader.h" +#include "XmlReader.h" +#include "XmlWriter.h" +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { +namespace { + +std::unique_ptr DataSetFromXml(const std::string& xmlFn) +{ + std::ifstream in(xmlFn); + if (!in) throw std::runtime_error{"DataSet: could not open XML file for reading: " + xmlFn}; + return XmlReader::FromStream(in); +} + +std::unique_ptr DataSetFromBam(const std::string& bamFn) +{ + // peek at sort order to determine if file should be an AlignmentSet or else SubreadSet + const auto bamFile = BamFile{bamFn}; + const auto& header = bamFile.Header(); + const auto aligned = header.SortOrder() == "coordinate"; + + std::unique_ptr dataset; + if (aligned) + dataset = std::make_unique(); + else + dataset = std::make_unique(); + + auto& resources = dataset->ExternalResources(); + resources.Add(ExternalResource(BamFile(bamFn))); + return dataset; +} + +std::unique_ptr DataSetFromFasta(const std::string& fasta) +{ + // make FASTA data set + auto dataset = std::make_unique(); + auto& resources = dataset->ExternalResources(); + resources.Add(ExternalResource("PacBio.ReferenceFile.ReferenceFastaFile", fasta)); + return dataset; +} + +std::unique_ptr DataSetFromFofn(const std::string& fofn) +{ + const auto fofnDir = FileUtils::DirectoryName(fofn); + std::ifstream in(fofn); + if (!in) throw std::runtime_error{"DataSet: could not open FOFN for reading: " + fofn}; + + auto filenames = FofnReader::Files(in); + std::transform( + filenames.begin(), filenames.end(), filenames.begin(), + [&fofnDir](const std::string fn) { return FileUtils::ResolvedFilePath(fn, fofnDir); }); + return DataSetIO::FromUris(filenames); +} + +std::unique_ptr DataSetFromUri(const std::string& uri) +{ + // NOTE: this says URI, but we're not quite handling filenames as true URIs + // basically just treating as a regular filename for now + + // handle on extension + if (boost::algorithm::iends_with(uri, ".xml")) + return DataSetFromXml(uri); + else if (boost::algorithm::iends_with(uri, ".bam")) + return DataSetFromBam(uri); + else if (boost::algorithm::iends_with(uri, ".fofn")) + return DataSetFromFofn(uri); + else if (boost::algorithm::iends_with(uri, ".fasta") || + boost::algorithm::iends_with(uri, ".fa")) { + return DataSetFromFasta(uri); + } + + // unknown filename extension + throw std::runtime_error{"DataSet: unsupported extension on input file: " + uri}; +} + +} // namespace + +std::unique_ptr DataSetIO::FromUri(const std::string& uri) +{ + return FromUris(std::vector(1, uri)); +} + +std::unique_ptr DataSetIO::FromUris(const std::vector& uris) +{ + if (uris.empty()) throw std::runtime_error{"DataSet: empty input URI list"}; + + // create dataset(s) from URI(s) + std::vector > datasets; + datasets.reserve(uris.size()); + for (const auto& uri : uris) + datasets.emplace_back(DataSetFromUri(uri)); + assert(!datasets.empty()); + + // if only 1, just return + if (datasets.size() == 1) return std::unique_ptr(datasets.front().release()); + + // else merge + else { + auto& result = datasets.at(0); + for (size_t i = 1; i < datasets.size(); ++i) { + const auto& next = datasets.at(i); + *result += *next; + } + return std::move(result); + } +} + +std::unique_ptr DataSetIO::FromXmlString(const std::string& xml) +{ + if (xml.empty()) throw std::runtime_error{"DataSet: cannot load from empty XML string"}; + std::istringstream s{xml}; + return XmlReader::FromStream(s); +} + +void DataSetIO::ToFile(const std::unique_ptr& dataset, const std::string& fn) +{ + DataSetIO::ToFile(*dataset, fn); +} + +void DataSetIO::ToStream(const std::unique_ptr& dataset, std::ostream& out) +{ + DataSetIO::ToStream(*dataset, out); +} + +void DataSetIO::ToFile(DataSetBase& dataset, const std::string& fn) +{ + std::ofstream out(fn); + if (!out) throw std::runtime_error{"DataSet: could not open XML file for writing: " + fn}; + XmlWriter::ToStream(dataset, out); +} + +void DataSetIO::ToStream(DataSetBase& dataset, std::ostream& out) +{ + XmlWriter::ToStream(dataset, out); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/DataSetIO.h b/src/DataSetIO.h new file mode 100644 index 0000000..733f69b --- /dev/null +++ b/src/DataSetIO.h @@ -0,0 +1,36 @@ +// Author: Derek Barnett + +#ifndef DATASETIO_H +#define DATASETIO_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +class DataSetIO +{ +public: + // input + static std::unique_ptr FromUri(const std::string& uri); + static std::unique_ptr FromUris(const std::vector& uris); + static std::unique_ptr FromXmlString(const std::string& xml); + + // output + static void ToFile(DataSetBase& dataset, const std::string& fn); + static void ToFile(const std::unique_ptr& dataset, const std::string& fn); + static void ToStream(DataSetBase& dataset, std::ostream& out); + static void ToStream(const std::unique_ptr& dataset, std::ostream& out); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // DATASETIO_H diff --git a/src/DataSetTypes.cpp b/src/DataSetTypes.cpp new file mode 100644 index 0000000..d45391f --- /dev/null +++ b/src/DataSetTypes.cpp @@ -0,0 +1,1176 @@ +// File Description +/// \file DataSetTypes.cpp +/// \brief Implementations for the public DataSet component classes. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/DataSetTypes.h" + +#include +#include +#include + +#include "pbbam/Unused.h" +#include "pbbam/internal/DataSetBaseTypes.h" + +#include "DataSetIO.h" +#include "DataSetUtils.h" +#include "FileUtils.h" +#include "TimeUtils.h" + +namespace { + +// clang-format off +using ElementType = PacBio::BAM::XmlElementType; +const std::unordered_map elementTypeLookup +{ + {"DataSetMetadata", ElementType::DATASET_METADATA}, + {"BioSample", ElementType::BIOSAMPLE}, + {"BioSamples", ElementType::BIOSAMPLES}, + {"DNABarcode", ElementType::DNA_BARCODE}, + {"DNABarcodes", ElementType::DNA_BARCODES}, + {"ExtensionElement", ElementType::EXTENSION}, + {"Extensions", ElementType::EXTENSIONS}, + {"ExternalResource", ElementType::EXTERNAL_RESOURCE}, + {"ExternalResources", ElementType::EXTERNAL_RESOURCES}, + {"FileIndex", ElementType::FILE_INDEX}, + {"FileIndices", ElementType::FILE_INDICES}, + {"Filter", ElementType::FILTER}, + {"Filters", ElementType::FILTERS}, + {"ParentTool", ElementType::PARENT_TOOL}, + {"Property", ElementType::PROPERTY}, + {"Properties", ElementType::PROPERTIES}, + {"Provenance", ElementType::PROVENANCE}, + {"AlignmentSet", ElementType::ALIGNMENT_SET}, + {"BarcodeSet", ElementType::BARCODE_SET}, + {"ConsensusAlignmentSet", ElementType::CONSENSUS_ALIGNMENT_SET}, + {"ConsensusReadSet", ElementType::CONSENSUS_READ_SET}, + {"ContigSet", ElementType::CONTIG_SET}, + {"HdfSubreadSet", ElementType::HDF_SUBREAD_SET}, + {"ReferenceSet", ElementType::REFERENCE_SET}, + {"SubreadSet", ElementType::SUBREAD_SET}, + {"TranscriptSet", ElementType::TRANSCRIPT_SET}, + {"TranscriptAlignmentSet", ElementType::TRANSCRIPT_ALIGNMENT_SET}, + {"DataSets", ElementType::SUBDATASETS}, + {"DataSet", ElementType::GENERIC_DATASET} +}; +// clang-format on + +} // namespace + +namespace PacBio { +namespace BAM { + +// ------------------- +// AlignmentSet +// ------------------- + +AlignmentSet::AlignmentSet() + : DataSetBase("PacBio.DataSet.AlignmentSet", "AlignmentSet", XsdType::DATASETS) +{ +} + +AlignmentSet::AlignmentSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "AlignmentSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// BarcodeSet +// ------------------- + +BarcodeSet::BarcodeSet() : DataSetBase("PacBio.DataSet.BarcodeSet", "BarcodeSet", XsdType::DATASETS) +{ +} + +BarcodeSet::BarcodeSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "BarcodeSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// BioSample +// ------------------- + +BioSample::BioSample(const std::string& name) : DataSetElement("BioSample", XsdType::SAMPLE_INFO) +{ + Name(name); +} + +BioSample::BioSample(const std::string& name, const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::SAMPLE_INFO) +{ + Name(name); +} + +DEFINE_ACCESSORS(BioSample, DNABarcodes, DNABarcodes) + +BioSample& BioSample::DNABarcodes(const PacBio::BAM::DNABarcodes& barcodes) +{ + DNABarcodes() = barcodes; + return *this; +} + +const std::string& BioSample::Name() const { return Attribute("Name"); } + +std::string& BioSample::Name() { return Attribute("Name"); } + +BioSample& BioSample::Name(const std::string& name) +{ + Attribute("Name", name); + return *this; +} + +// ------------------- +// BioSamples +// ------------------- + +BioSamples::BioSamples() : DataSetElement("BioSamples", XsdType::SAMPLE_INFO) {} + +BioSamples::BioSamples(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::SAMPLE_INFO) +{ +} + +void BioSamples::Add(const BioSample& sample) { AddChild(sample); } + +void BioSamples::Remove(const BioSample& sample) { RemoveChild(sample); } + +BioSamples::iterator_type BioSamples::begin() { return BioSamples::iterator_type(this, 0); } + +BioSamples::const_iterator_type BioSamples::begin() const { return cbegin(); } + +BioSamples::const_iterator_type BioSamples::cbegin() const +{ + return BioSamples::const_iterator_type(this, 0); +} + +BioSamples::iterator_type BioSamples::end() +{ + return BioSamples::iterator_type(this, NumChildren()); +} + +BioSamples::const_iterator_type BioSamples::end() const { return cend(); } + +BioSamples::const_iterator_type BioSamples::cend() const +{ + return BioSamples::const_iterator_type(this, NumChildren()); +} + +const BioSamples::value_type& BioSamples::operator[](size_t index) const +{ + return dynamic_cast(*(children_.at(index).get())); +} + +BioSamples::value_type& BioSamples::operator[](size_t index) +{ + return dynamic_cast(*(children_.at(index).get())); +} + +// ----------------------- +// ConsensusAlignmentSet +// ----------------------- + +ConsensusAlignmentSet::ConsensusAlignmentSet() + : DataSetBase("PacBio.DataSet.ConsensusAlignmentSet", "ConsensusAlignmentSet", + XsdType::DATASETS) +{ +} + +ConsensusAlignmentSet::ConsensusAlignmentSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "ConsensusAlignmentSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// ConsensusReadSet +// ------------------- + +ConsensusReadSet::ConsensusReadSet() + : DataSetBase("PacBio.DataSet.ConsensusReadSet", "ConsensusReadSet", XsdType::DATASETS) +{ +} + +ConsensusReadSet::ConsensusReadSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "ConsensusReadSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// ContigSet +// ------------------- + +ContigSet::ContigSet() : DataSetBase("PacBio.DataSet.ContigSet", "ContigSet", XsdType::DATASETS) {} + +ContigSet::ContigSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "ContigSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// DataSetBase +// ------------------- + +DataSetBase::DataSetBase() + : StrictEntityType("PacBio.DataSet.DataSet", "DataSet", XsdType::DATASETS) + , path_(FileUtils::CurrentWorkingDirectory()) +{ +} + +DataSetBase::DataSetBase(const internal::FromInputXml& fromInputXml) + : StrictEntityType("", "DataSet", fromInputXml, XsdType::DATASETS) + , path_(FileUtils::CurrentWorkingDirectory()) +{ +} + +DataSetBase::DataSetBase(const std::string& metatype, const std::string& label, const XsdType& xsd) + : StrictEntityType(metatype, label, xsd), path_(FileUtils::CurrentWorkingDirectory()) +{ +} + +DataSetBase::DataSetBase(const std::string& metatype, const std::string& label, + const internal::FromInputXml& fromInputXml, const XsdType& xsd) + : StrictEntityType(metatype, label, fromInputXml, xsd) + , path_(FileUtils::CurrentWorkingDirectory()) +{ +} + +const PacBio::BAM::ExternalResources& DataSetBase::ExternalResources() const +{ + return Child("ExternalResources"); +} + +PacBio::BAM::ExternalResources& DataSetBase::ExternalResources() +{ + if (!HasChild("ExternalResources")) AddChild(PacBio::BAM::ExternalResources()); + auto& c = Child("ExternalResources"); + return c; +} + +DataSetBase& DataSetBase::ExternalResources(const PacBio::BAM::ExternalResources& resources) +{ + ExternalResources() = resources; + return *this; +} + +DEFINE_ACCESSORS(DataSetBase, Filters, Filters) + +DataSetBase& DataSetBase::Filters(const PacBio::BAM::Filters& filters) +{ + Filters() = filters; + return *this; +} + +bool DataSetBase::FromInputXml() const { return fromInputXml_; } + +void DataSetBase::FromInputXml(bool ok) { fromInputXml_ = ok; } + +DEFINE_ACCESSORS(DataSetBase, DataSetMetadata, Metadata) + +DataSetBase& DataSetBase::Metadata(const PacBio::BAM::DataSetMetadata& metadata) +{ + Metadata() = metadata; + return *this; +} + +const NamespaceRegistry& DataSetBase::Namespaces() const { return registry_; } + +NamespaceRegistry& DataSetBase::Namespaces() { return registry_; } + +void DataSetBase::Path(const std::string& path) { path_ = path; } + +const std::string& DataSetBase::Path() const { return path_; } + +const PacBio::BAM::SubDataSets& DataSetBase::SubDataSets() const +{ + try { + return Child("DataSets"); + } catch (std::exception&) { + return internal::NullObject(); + } +} + +PacBio::BAM::SubDataSets& DataSetBase::SubDataSets() +{ + if (!HasChild("DataSets")) AddChild(internal::NullObject()); + return Child("DataSets"); +} + +DataSetBase& DataSetBase::SubDataSets(const PacBio::BAM::SubDataSets& subdatasets) +{ + SubDataSets() = subdatasets; + return *this; +} + +DataSetBase* DataSetBase::DeepCopy() const +{ + auto* copyDataset = new DataSetElement(*this); + auto* result = static_cast(copyDataset); + result->registry_ = registry_; + result->path_ = path_; + return result; +} + +DataSetBase& DataSetBase::operator+=(const DataSetBase& other) +{ + // must be same dataset types (or 'other' must be generic) + if (other.LocalNameLabel() != LocalNameLabel() && other.LocalNameLabel() != "DataSet") + throw std::runtime_error{"DataSet: cannot merge different dataset types"}; + + // check object metadata + Metadata() += other.Metadata(); + ExternalResources() += other.ExternalResources(); + Filters() += other.Filters(); + SubDataSets() += other; + + return *this; +} + +std::shared_ptr DataSetBase::Create(const std::string& typeName) +{ + if (typeName == std::string("DataSet")) return std::make_shared(); + if (typeName == std::string("SubreadSet")) return std::make_shared(); + if (typeName == std::string("AlignmentSet")) return std::make_shared(); + if (typeName == std::string("BarcodeSet")) return std::make_shared(); + if (typeName == std::string("ConsensusAlignmentSet")) + return std::make_shared(); + if (typeName == std::string("ConsensusReadSet")) return std::make_shared(); + if (typeName == std::string("ContigSet")) return std::make_shared(); + if (typeName == std::string("HdfSubreadSet")) return std::make_shared(); + if (typeName == std::string("ReferenceSet")) return std::make_shared(); + if (typeName == std::string("TranscriptSet")) return std::make_shared(); + if (typeName == std::string("TranscriptAlignmentSet")) + return std::make_shared(); + + // unknown typename + throw std::runtime_error{"DataSet: unsupported type: " + typeName}; +} + +std::shared_ptr DataSetBase::Create(const std::string& typeName, + const internal::FromInputXml& fromInputXml) +{ + if (typeName == std::string("DataSet")) return std::make_shared(fromInputXml); + if (typeName == std::string("SubreadSet")) return std::make_shared(fromInputXml); + if (typeName == std::string("AlignmentSet")) + return std::make_shared(fromInputXml); + if (typeName == std::string("BarcodeSet")) return std::make_shared(fromInputXml); + if (typeName == std::string("ConsensusAlignmentSet")) + return std::make_shared(fromInputXml); + if (typeName == std::string("ConsensusReadSet")) + return std::make_shared(fromInputXml); + if (typeName == std::string("ContigSet")) return std::make_shared(fromInputXml); + if (typeName == std::string("HdfSubreadSet")) + return std::make_shared(fromInputXml); + if (typeName == std::string("ReferenceSet")) + return std::make_shared(fromInputXml); + if (typeName == std::string("TranscriptSet")) + return std::make_shared(fromInputXml); + if (typeName == std::string("TranscriptAlignmentSet")) + return std::make_shared(fromInputXml); + + // unknown typename + throw std::runtime_error{"DataSet: unsupported type: " + typeName}; +} + +void DataSetBase::Save(const std::string& outputFilename) +{ + DataSetIO::ToFile(*this, outputFilename); +} + +void DataSetBase::SaveToStream(std::ostream& out) { DataSetIO::ToStream(*this, out); } + +// ------------------- +// DataSetMetadata +// ------------------- + +DataSetMetadata::DataSetMetadata() : DataSetElement("DataSetMetadata", XsdType::DATASETS) {} + +DataSetMetadata::DataSetMetadata(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::DATASETS) +{ +} + +DataSetMetadata::DataSetMetadata(const std::string& numRecords, const std::string& totalLength) + : DataSetElement("DataSetMetadata", XsdType::DATASETS) +{ + TotalLength(totalLength); + NumRecords(numRecords); +} + +DataSetMetadata::DataSetMetadata(const std::string& numRecords, const std::string& totalLength, + const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::DATASETS) +{ + TotalLength(totalLength); + NumRecords(numRecords); +} + +DEFINE_ACCESSORS(DataSetMetadata, BioSamples, BioSamples) + +DataSetMetadata& DataSetMetadata::BioSamples(const PacBio::BAM::BioSamples& samples) +{ + BioSamples() = samples; + return *this; +} + +DEFINE_ACCESSORS(DataSetMetadata, Provenance, Provenance) + +DataSetMetadata& DataSetMetadata::Provenance(const PacBio::BAM::Provenance& provenance) +{ + Provenance() = provenance; + return *this; +} + +DataSetMetadata& DataSetMetadata::operator+=(const DataSetMetadata& other) +{ + TotalLength() = TotalLength() + other.TotalLength(); + NumRecords() = NumRecords() + other.NumRecords(); + // merge add'l + return *this; +} + +const std::string& DataSetMetadata::NumRecords() const { return ChildText("NumRecords"); } + +std::string& DataSetMetadata::NumRecords() { return ChildText("NumRecords"); } + +DataSetMetadata& DataSetMetadata::NumRecords(const std::string& numRecords) +{ + ChildText("NumRecords", numRecords); + return *this; +} + +const std::string& DataSetMetadata::TotalLength() const { return ChildText("TotalLength"); } + +std::string& DataSetMetadata::TotalLength() { return ChildText("TotalLength"); } + +DataSetMetadata& DataSetMetadata::TotalLength(const std::string& totalLength) +{ + ChildText("TotalLength", totalLength); + return *this; +} + +// ------------------- +// DNABarcode +// ------------------- + +DNABarcode::DNABarcode(const std::string& name) : DataSetElement("DNABarcode", XsdType::SAMPLE_INFO) +{ + Name(name); + UniqueId(internal::GenerateUuid()); +} + +DNABarcode::DNABarcode(const std::string& name, const std::string& uuid) + : DataSetElement("DNABarcode", XsdType::SAMPLE_INFO) +{ + Name(name); + UniqueId(uuid); +} + +DNABarcode::DNABarcode(const std::string& name, const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::SAMPLE_INFO) +{ + Name(name); + UniqueId(internal::GenerateUuid()); +} + +DNABarcode::DNABarcode(const std::string& name, const std::string& uuid, + const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::SAMPLE_INFO) +{ + Name(name); + UniqueId(uuid); +} + +const std::string& DNABarcode::Name() const { return Attribute("Name"); } + +std::string& DNABarcode::Name() { return Attribute("Name"); } + +DNABarcode& DNABarcode::Name(const std::string& name) +{ + Attribute("Name", name); + return *this; +} + +const std::string& DNABarcode::UniqueId() const { return Attribute("UniqueId"); } + +std::string& DNABarcode::UniqueId() { return Attribute("UniqueId"); } + +DNABarcode& DNABarcode::UniqueId(const std::string& uuid) +{ + Attribute("UniqueId", uuid); + return *this; +} + +// ------------------- +// DNABarcodes +// ------------------- + +DNABarcodes::DNABarcodes() : DataSetElement("DNABarcodes", XsdType::SAMPLE_INFO) {} + +DNABarcodes::DNABarcodes(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::SAMPLE_INFO) +{ +} + +void DNABarcodes::Add(const DNABarcode& barcode) { AddChild(barcode); } + +void DNABarcodes::Remove(const DNABarcode& barcode) { RemoveChild(barcode); } + +DNABarcodes::iterator_type DNABarcodes::begin() { return DNABarcodes::iterator_type(this, 0); } + +DNABarcodes::const_iterator_type DNABarcodes::begin() const { return cbegin(); } + +DNABarcodes::const_iterator_type DNABarcodes::cbegin() const +{ + return DNABarcodes::const_iterator_type(this, 0); +} + +DNABarcodes::iterator_type DNABarcodes::end() +{ + return DNABarcodes::iterator_type(this, NumChildren()); +} + +DNABarcodes::const_iterator_type DNABarcodes::end() const { return cend(); } + +DNABarcodes::const_iterator_type DNABarcodes::cend() const +{ + return DNABarcodes::const_iterator_type(this, NumChildren()); +} + +const DNABarcodes::value_type& DNABarcodes::operator[](size_t index) const +{ + return dynamic_cast(*(children_.at(index).get())); +} + +DNABarcodes::value_type& DNABarcodes::operator[](size_t index) +{ + return dynamic_cast(*(children_.at(index).get())); +} + +// ------------------- +// ExtensionElement +// ------------------- + +ExtensionElement::ExtensionElement() : DataSetElement("ExtensionElement", XsdType::BASE_DATA_MODEL) +{ +} + +ExtensionElement::ExtensionElement(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::BASE_DATA_MODEL) +{ +} + +// ------------------- +// Extensions +// ------------------- + +Extensions::Extensions() : DataSetElement("Extensions", XsdType::BASE_DATA_MODEL) {} + +Extensions::Extensions(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::BASE_DATA_MODEL) +{ +} + +Extensions::iterator_type Extensions::begin() { return Extensions::iterator_type(this, 0); } + +Extensions::const_iterator_type Extensions::begin() const { return cbegin(); } + +Extensions::const_iterator_type Extensions::cbegin() const +{ + return Extensions::const_iterator_type(this, 0); +} + +Extensions::iterator_type Extensions::end() +{ + return Extensions::iterator_type(this, NumChildren()); +} + +Extensions::const_iterator_type Extensions::end() const { return cend(); } + +Extensions::const_iterator_type Extensions::cend() const +{ + return Extensions::const_iterator_type(this, NumChildren()); +} + +const Extensions::value_type& Extensions::operator[](size_t index) const +{ + return dynamic_cast(*(children_.at(index).get())); +} + +Extensions::value_type& Extensions::operator[](size_t index) +{ + return dynamic_cast(*(children_.at(index).get())); +} + +// ------------------- +// ExternalResource +// ------------------- + +ExternalResource::ExternalResource(const BamFile& bamFile) + : IndexedDataType("PacBio.SubreadFile.SubreadBamFile", bamFile.Filename(), "ExternalResource", + XsdType::BASE_DATA_MODEL) +{ +} + +ExternalResource::ExternalResource(const std::string& metatype, const std::string& filename) + : IndexedDataType(metatype, filename, "ExternalResource", XsdType::BASE_DATA_MODEL) +{ +} + +ExternalResource::ExternalResource(const std::string& metatype, const std::string& filename, + const internal::FromInputXml& fromInputXml) + : IndexedDataType("", filename, "ExternalResource", fromInputXml, XsdType::BASE_DATA_MODEL) +{ + UNUSED(metatype); +} + +DEFINE_ACCESSORS(ExternalResource, ExternalResources, ExternalResources) + +ExternalResource& ExternalResource::ExternalResources( + const PacBio::BAM::ExternalResources& resources) +{ + ExternalResources() = resources; + return *this; +} + +BamFile ExternalResource::ToBamFile() const { return BamFile(ResourceId()); } + +// ------------------- +// ExternalResources +// ------------------- + +ExternalResources::ExternalResources() + : DataSetElement("ExternalResources", XsdType::BASE_DATA_MODEL) +{ +} + +ExternalResources::ExternalResources(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::BASE_DATA_MODEL) +{ +} + +ExternalResources& ExternalResources::operator+=(const ExternalResources& other) +{ + // only keep unique resource ids + std::set myResourceIds; + for (size_t i = 0; i < NumChildren(); ++i) { + const ExternalResource& resource = this->operator[](i); + myResourceIds.insert(resource.ResourceId()); + } + + std::vector newResourceIndices; + const size_t numOtherResourceIds = other.Size(); + for (size_t i = 0; i < numOtherResourceIds; ++i) { + const std::string& resourceId = other[i].ResourceId(); + auto found = myResourceIds.find(resourceId); + if (found == myResourceIds.cend()) newResourceIndices.push_back(i); + } + + for (size_t index : newResourceIndices) + Add(other[index]); + return *this; +} + +void ExternalResources::Add(const ExternalResource& ext) +{ + // disallow external resources w/ duplicate ResourceIds + std::set myResourceIds; + for (size_t i = 0; i < NumChildren(); ++i) { + const ExternalResource& resource = this->operator[](i); + myResourceIds.insert(resource.ResourceId()); + } + + if (myResourceIds.find(ext.ResourceId()) == myResourceIds.cend()) AddChild(ext); +} + +std::vector ExternalResources::BamFiles() const +{ + + std::vector result; + const int numResources = Size(); + result.reserve(numResources); + for (const ExternalResource& ext : *this) + result.push_back(ext.ToBamFile()); + return result; +} + +void ExternalResources::Remove(const ExternalResource& ext) { RemoveChild(ext); } + +ExternalResources::iterator_type ExternalResources::begin() +{ + return ExternalResources::iterator_type(this, 0); +} + +ExternalResources::const_iterator_type ExternalResources::begin() const { return cbegin(); } + +ExternalResources::const_iterator_type ExternalResources::cbegin() const +{ + return ExternalResources::const_iterator_type(this, 0); +} + +ExternalResources::iterator_type ExternalResources::end() +{ + return ExternalResources::iterator_type(this, NumChildren()); +} + +ExternalResources::const_iterator_type ExternalResources::end() const { return cend(); } + +ExternalResources::const_iterator_type ExternalResources::cend() const +{ + return ExternalResources::const_iterator_type(this, NumChildren()); +} + +const ExternalResources::value_type& ExternalResources::operator[](size_t index) const +{ + return dynamic_cast(*(children_.at(index).get())); +} + +ExternalResources::value_type& ExternalResources::operator[](size_t index) +{ + return dynamic_cast(*(children_.at(index).get())); +} + +// ------------------- +// FileIndex +// ------------------- + +FileIndex::FileIndex(const std::string& metatype, const std::string& filename) + : InputOutputDataType(metatype, filename, "FileIndex", XsdType::BASE_DATA_MODEL) +{ +} + +FileIndex::FileIndex(const std::string& metatype, const std::string& filename, + const internal::FromInputXml& fromInputXml) + : InputOutputDataType("", filename, "FileIndex", fromInputXml, XsdType::BASE_DATA_MODEL) +{ + UNUSED(metatype); +} + +// ------------------- +// FileIndices +// ------------------- + +FileIndices::FileIndices() : DataSetElement("FileIndices", XsdType::BASE_DATA_MODEL) {} + +FileIndices::FileIndices(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::BASE_DATA_MODEL) +{ +} + +void FileIndices::Add(const FileIndex& index) { AddChild(index); } + +void FileIndices::Remove(const FileIndex& index) { RemoveChild(index); } + +FileIndices::iterator_type FileIndices::begin() { return FileIndices::iterator_type(this, 0); } + +FileIndices::const_iterator_type FileIndices::begin() const { return cbegin(); } + +FileIndices::const_iterator_type FileIndices::cbegin() const +{ + return FileIndices::const_iterator_type(this, 0); +} + +FileIndices::iterator_type FileIndices::end() +{ + return FileIndices::iterator_type(this, NumChildren()); +} + +FileIndices::const_iterator_type FileIndices::end() const { return cend(); } + +FileIndices::const_iterator_type FileIndices::cend() const +{ + return FileIndices::const_iterator_type(this, NumChildren()); +} + +const FileIndices::value_type& FileIndices::operator[](size_t index) const +{ + return dynamic_cast(*(children_.at(index).get())); +} + +FileIndices::value_type& FileIndices::operator[](size_t index) +{ + return dynamic_cast(*(children_.at(index).get())); +} + +// ------------------- +// Filter +// ------------------- + +Filter::Filter() : DataSetElement("Filter", XsdType::DATASETS) {} + +Filter::Filter(const internal::FromInputXml& fromInputXml) + : DataSetElement("Filter", fromInputXml, XsdType::DATASETS) +{ +} + +DEFINE_ACCESSORS(Filter, Properties, Properties) + +Filter& Filter::Properties(const PacBio::BAM::Properties& properties) +{ + Properties() = properties; + return *this; +} + +// ------------------- +// Filters +// ------------------- + +Filters::Filters() : DataSetElement("Filters", XsdType::DATASETS) {} + +Filters::Filters(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::DATASETS) +{ +} + +Filters& Filters::operator+=(const Filters& other) +{ + for (auto& newFilter : other) + AddChild(newFilter); + return *this; +} + +void Filters::Add(const Filter& filter) { AddChild(filter); } + +void Filters::Remove(const Filter& filter) { RemoveChild(filter); } + +Filters::iterator_type Filters::begin() { return Filters::iterator_type(this, 0); } + +Filters::const_iterator_type Filters::begin() const { return cbegin(); } + +Filters::const_iterator_type Filters::cbegin() const +{ + return Filters::const_iterator_type(this, 0); +} + +Filters::iterator_type Filters::end() { return Filters::iterator_type(this, NumChildren()); } + +Filters::const_iterator_type Filters::end() const { return cend(); } + +Filters::const_iterator_type Filters::cend() const +{ + return Filters::const_iterator_type(this, NumChildren()); +} + +const Filters::value_type& Filters::operator[](size_t index) const +{ + return dynamic_cast(*(children_.at(index).get())); +} + +Filters::value_type& Filters::operator[](size_t index) +{ + return dynamic_cast(*(children_.at(index).get())); +} + +// ------------------- +// HdfSubreadSet +// ------------------- + +HdfSubreadSet::HdfSubreadSet() + : DataSetBase("PacBio.DataSet.HdfSubreadSet", "HdfSubreadSet", XsdType::DATASETS) +{ +} + +HdfSubreadSet::HdfSubreadSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "HdfSubreadSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// ParentTool +// ------------------- + +ParentTool::ParentTool() : BaseEntityType("ParentTool", XsdType::DATASETS) {} + +ParentTool::ParentTool(const internal::FromInputXml& fromInputXml) + : BaseEntityType("", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// Properties +// ------------------- + +Properties::Properties() : DataSetElement("Properties", XsdType::BASE_DATA_MODEL) {} + +Properties::Properties(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::BASE_DATA_MODEL) +{ +} + +void Properties::Add(const Property& property) { AddChild(property); } + +void Properties::Remove(const Property& property) { RemoveChild(property); } + +Properties::iterator_type Properties::begin() { return Properties::iterator_type(this, 0); } + +Properties::const_iterator_type Properties::begin() const { return cbegin(); } + +Properties::const_iterator_type Properties::cbegin() const +{ + return Properties::const_iterator_type(this, 0); +} + +Properties::iterator_type Properties::end() +{ + return Properties::iterator_type(this, NumChildren()); +} + +Properties::const_iterator_type Properties::end() const { return cend(); } + +Properties::const_iterator_type Properties::cend() const +{ + return Properties::const_iterator_type(this, NumChildren()); +} + +const Properties::value_type& Properties::operator[](size_t index) const +{ + return dynamic_cast(*(children_.at(index).get())); +} + +Properties::value_type& Properties::operator[](size_t index) +{ + return dynamic_cast(*(children_.at(index).get())); +} + +// ------------------- +// Property +// ------------------- + +Property::Property(const std::string& name, const std::string& value, const std::string& op) + : DataSetElement("Property", XsdType::BASE_DATA_MODEL) +{ + Name(name); + Value(value); + Operator(op); +} + +Property::Property(const std::string& name, const std::string& value, const std::string& op, + const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::BASE_DATA_MODEL) +{ + Name(name); + Value(value); + Operator(op); +} + +const std::string& Property::Name() const { return Attribute("Name"); } + +std::string& Property::Name() { return Attribute("Name"); } + +Property& Property::Name(const std::string& name) +{ + Attribute("Name", name); + return *this; +} + +const std::string& Property::Operator() const { return Attribute("Operator"); } + +std::string& Property::Operator() { return Attribute("Operator"); } + +Property& Property::Operator(const std::string& op) +{ + Attribute("Operator", op); + return *this; +} + +const std::string& Property::Value() const { return Attribute("Value"); } + +std::string& Property::Value() { return Attribute("Value"); } + +Property& Property::Value(const std::string& value) +{ + Attribute("Value", value); + return *this; +} + +// ------------------- +// Provenance +// ------------------- + +Provenance::Provenance() : DataSetElement("Provenance", XsdType::DATASETS) {} + +Provenance::Provenance(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::DATASETS) +{ +} + +DEFINE_ACCESSORS(Provenance, ParentTool, ParentTool) + +const std::string& Provenance::CreatedBy() const { return Attribute("CreatedBy"); } + +std::string& Provenance::CreatedBy() { return Attribute("CreatedBy"); } + +Provenance& Provenance::CreatedBy(const std::string& createdBy) +{ + Attribute("CreatedBy", createdBy); + return *this; +} + +const std::string& Provenance::CommonServicesInstanceId() const +{ + return ChildText("CommonServicesInstanceId"); +} + +std::string& Provenance::CommonServicesInstanceId() +{ + return ChildText("CommonServicesInstanceId"); +} + +Provenance& Provenance::CommonServicesInstanceId(const std::string& id) +{ + ChildText("CommonServicesInstanceId", id); + return *this; +} + +const std::string& Provenance::CreatorUserId() const { return ChildText("CreatorUserId"); } + +std::string& Provenance::CreatorUserId() { return ChildText("CreatorUserId"); } + +Provenance& Provenance::CreatorUserId(const std::string& id) +{ + ChildText("CreatorUserId", id); + return *this; +} + +const std::string& Provenance::ParentJobId() const { return ChildText("ParentJobId"); } + +std::string& Provenance::ParentJobId() { return ChildText("ParentJobId"); } + +Provenance& Provenance::ParentJobId(const std::string& id) +{ + ChildText("ParentJobId", id); + return *this; +} + +Provenance& Provenance::ParentTool(const PacBio::BAM::ParentTool& tool) +{ + ParentTool() = tool; + return *this; +} + +// ------------------- +// ReferenceSet +// ------------------- + +ReferenceSet::ReferenceSet() + : DataSetBase("PacBio.DataSet.ReferenceSet", "ReferenceSet", XsdType::DATASETS) +{ +} + +ReferenceSet::ReferenceSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "ReferenceSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// SubDataSets +// ------------------- + +SubDataSets::SubDataSets() : DataSetElement("DataSets", XsdType::DATASETS) {} + +SubDataSets::SubDataSets(const internal::FromInputXml& fromInputXml) + : DataSetElement("", fromInputXml, XsdType::DATASETS) +{ +} + +SubDataSets& SubDataSets::operator+=(const DataSetBase& other) +{ + AddChild(other); + return *this; +} + +SubDataSets& SubDataSets::operator+=(const SubDataSets& other) +{ + for (auto& newSubDataset : other) + AddChild(newSubDataset); + return *this; +} + +void SubDataSets::Add(const DataSetBase& subdataset) { AddChild(subdataset); } + +void SubDataSets::Remove(const DataSetBase& subdataset) { RemoveChild(subdataset); } + +SubDataSets::iterator_type SubDataSets::begin() { return SubDataSets::iterator_type(this, 0); } + +SubDataSets::const_iterator_type SubDataSets::begin() const { return cbegin(); } + +SubDataSets::const_iterator_type SubDataSets::cbegin() const +{ + return SubDataSets::const_iterator_type(this, 0); +} + +SubDataSets::iterator_type SubDataSets::end() +{ + return SubDataSets::iterator_type(this, NumChildren()); +} + +SubDataSets::const_iterator_type SubDataSets::end() const { return cend(); } + +SubDataSets::const_iterator_type SubDataSets::cend() const +{ + return SubDataSets::const_iterator_type(this, NumChildren()); +} + +const SubDataSets::value_type& SubDataSets::operator[](size_t index) const +{ + return dynamic_cast(*(children_.at(index).get())); +} + +SubDataSets::value_type& SubDataSets::operator[](size_t index) +{ + return dynamic_cast(*(children_.at(index).get())); +} + +// ------------------- +// SubreadSet +// ------------------- + +SubreadSet::SubreadSet() : DataSetBase("PacBio.DataSet.SubreadSet", "SubreadSet", XsdType::DATASETS) +{ +} + +SubreadSet::SubreadSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "SubreadSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// TranscriptSet +// ------------------- + +TranscriptSet::TranscriptSet() + : DataSetBase("PacBio.DataSet.TranscriptSet", "TranscriptSet", XsdType::DATASETS) +{ +} + +TranscriptSet::TranscriptSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "TranscriptSet", fromInputXml, XsdType::DATASETS) +{ +} + +// ------------------- +// TranscriptAlignmentSet +// ------------------- + +TranscriptAlignmentSet::TranscriptAlignmentSet() + : DataSetBase("PacBio.DataSet.TranscriptAlignmentSet", "TranscriptAlignmentSet", + XsdType::DATASETS) +{ +} + +TranscriptAlignmentSet::TranscriptAlignmentSet(const internal::FromInputXml& fromInputXml) + : DataSetBase("", "TranscriptAlignmentSet", fromInputXml, XsdType::DATASETS) +{ +} + +XmlElementType ElementTypeFromName(const std::string& name) +{ + const auto found = elementTypeLookup.find(name); + if (found == elementTypeLookup.cend()) return XmlElementType::GENERIC_ELEMENT; + return found->second; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/DataSetUtils.h b/src/DataSetUtils.h new file mode 100644 index 0000000..5a843d3 --- /dev/null +++ b/src/DataSetUtils.h @@ -0,0 +1,73 @@ +// Author: Derek Barnett + +#ifndef DATASETUTILS_H +#define DATASETUTILS_H + +#include "pbbam/Config.h" + +#include +#include + +#include + +namespace PacBio { +namespace BAM { +namespace internal { + +static const std::string XML_VERSION = std::string{"3.0.1"}; + +template +inline const T& NullObject() +{ + static const T empty; + return empty; +} + +template <> +inline const PacBio::BAM::DataSetMetadata& NullObject() +{ + static const PacBio::BAM::DataSetMetadata empty("", ""); + return empty; +} + +inline std::string GenerateUuid() +{ + static boost::uuids::random_generator gen; + const boost::uuids::uuid uuid = gen(); + return boost::uuids::to_string(uuid); +} + +} // namespace internal +} // namespace BAM +} // namespace PacBio + +#ifndef FETCH_CHILD_CONST_REF +#define FETCH_CHILD_CONST_REF(Class, Type, Method) \ + \ + const PacBio::BAM::Type& Class::Method() const \ + { \ + try { \ + return Child(#Type); \ + } catch (std::exception&) { \ + return internal::NullObject(); \ + } \ + } +#endif + +#ifndef FETCH_CHILD_REF +#define FETCH_CHILD_REF(Class, Type, Method) \ + \ + PacBio::BAM::Type& Class::Method() \ + { \ + if (!HasChild(#Type)) AddChild(internal::NullObject()); \ + return Child(#Type); \ + } +#endif + +#ifndef DEFINE_ACCESSORS +#define DEFINE_ACCESSORS(Class, Type, Method) \ + FETCH_CHILD_CONST_REF(Class, Type, Method) \ + FETCH_CHILD_REF(Class, Type, Method) +#endif + +#endif // DATASETUTILS_H diff --git a/src/DataSetXsd.cpp b/src/DataSetXsd.cpp new file mode 100644 index 0000000..2151fd2 --- /dev/null +++ b/src/DataSetXsd.cpp @@ -0,0 +1,226 @@ +// File Description +/// \file DataSetXsd.cpp +/// \brief Implements the XSD- and namespace-related classes for DataSetXML. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/DataSetXsd.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { +namespace internal { + +// clang-format off +static std::map DefaultRegistry() +{ + const auto result = std::map + { + { XsdType::NONE, NamespaceInfo{ "", "" } }, + { XsdType::AUTOMATION_CONSTRAINTS, NamespaceInfo{ "", "http://pacificbiosciences.com/PacBioAutomationConstraints.xsd" } }, + { XsdType::BASE_DATA_MODEL, NamespaceInfo{ "pbbase", "http://pacificbiosciences.com/PacBioBaseDataModel.xsd" } }, + { XsdType::COLLECTION_METADATA, NamespaceInfo{ "pbmeta", "http://pacificbiosciences.com/PacBioCollectionMetadata.xsd" } }, + { XsdType::COMMON_MESSAGES, NamespaceInfo{ "", "http://pacificbiosciences.com/PacBioCommonMessages.xsd" } }, + { XsdType::DATA_MODEL, NamespaceInfo{ "pbdm", "http://pacificbiosciences.com/PacBioDataModel.xsd" } }, + { XsdType::DATA_STORE, NamespaceInfo{ "", "http://pacificbiosciences.com/PacBioDataStore.xsd" } }, + { XsdType::DATASETS, NamespaceInfo{ "pbds", "http://pacificbiosciences.com/PacBioDatasets.xsd" } }, + { XsdType::DECL_DATA, NamespaceInfo{ "", "http://pacificbiosciences.com/PacBioDeclData.xsd" } }, + { XsdType::PART_NUMBERS, NamespaceInfo{ "pbpn", "http://pacificbiosciences.com/PacBioPartNumbers.xsd" } }, + { XsdType::PRIMARY_METRICS, NamespaceInfo{ "", "http://pacificbiosciences.com/PacBioPrimaryMetrics.xsd" } }, + { XsdType::REAGENT_KIT, NamespaceInfo{ "pbrk", "http://pacificbiosciences.com/PacBioReagentKit.xsd" } }, + { XsdType::RIGHTS_AND_ROLES, NamespaceInfo{ "", "http://pacificbiosciences.com/PacBioRightsAndRoles.xsd" } }, + { XsdType::SAMPLE_INFO, NamespaceInfo{ "pbsample", "http://pacificbiosciences.com/PacBioSampleInfo.xsd" } }, + { XsdType::SEEDING_DATA, NamespaceInfo{ "", "http://pacificbiosciences.com/PacBioSeedingData.xsd" } } + }; + return result; +} + +static const auto elementRegistry = std::unordered_map +{ + // 'pbbase' elements + // + { "AutomationParameter" , XsdType::BASE_DATA_MODEL }, + { "AutomationParameters" , XsdType::BASE_DATA_MODEL }, + { "BinCount" , XsdType::BASE_DATA_MODEL }, + { "BinCounts" , XsdType::BASE_DATA_MODEL }, + { "BinLabel" , XsdType::BASE_DATA_MODEL }, + { "BinLabels" , XsdType::BASE_DATA_MODEL }, + { "BinWidth" , XsdType::BASE_DATA_MODEL }, + { "ExternalResource" , XsdType::BASE_DATA_MODEL }, + { "ExternalResources" , XsdType::BASE_DATA_MODEL }, + { "FileIndex" , XsdType::BASE_DATA_MODEL }, + { "FileIndices" , XsdType::BASE_DATA_MODEL }, + { "MaxBinValue" , XsdType::BASE_DATA_MODEL }, + { "MaxOutlierValue" , XsdType::BASE_DATA_MODEL }, + { "MetricDescription" , XsdType::BASE_DATA_MODEL }, + { "NumBins" , XsdType::BASE_DATA_MODEL }, + { "Properties" , XsdType::BASE_DATA_MODEL }, + { "Property" , XsdType::BASE_DATA_MODEL }, + { "Sample95thPct" , XsdType::BASE_DATA_MODEL }, + { "SampleMean" , XsdType::BASE_DATA_MODEL }, + { "SampleMed" , XsdType::BASE_DATA_MODEL }, + { "SampleSize" , XsdType::BASE_DATA_MODEL }, + { "SampleStd" , XsdType::BASE_DATA_MODEL }, + + // 'pbds' elements + // + { "AdapterDimerFraction", XsdType::DATASETS }, + { "AlignmentSet", XsdType::DATASETS }, + { "BarcodeConstruction", XsdType::DATASETS }, + { "BarcodeSet", XsdType::DATASETS }, + { "ConsensusAlignmentSet", XsdType::DATASETS }, + { "ConsensusReadSet", XsdType::DATASETS }, + { "Contig", XsdType::DATASETS }, + { "Contigs", XsdType::DATASETS }, + { "ContigSet", XsdType::DATASETS }, + { "ControlReadLenDist", XsdType::DATASETS }, + { "ControlReadQualDist", XsdType::DATASETS }, + { "DataSetMetdata", XsdType::DATASETS }, + { "DataSet", XsdType::DATASETS }, + { "DataSets", XsdType::DATASETS }, + { "Filter", XsdType::DATASETS }, + { "Filters", XsdType::DATASETS }, + { "HdfSubreadSet", XsdType::DATASETS }, + { "InsertReadLenDist", XsdType::DATASETS }, + { "InsertReadQualDist" , XsdType::DATASETS }, + { "MedianInsertDist", XsdType::DATASETS }, + { "NumRecords", XsdType::DATASETS }, + { "NumSequencingZmws", XsdType::DATASETS }, + { "Organism", XsdType::DATASETS }, + { "ParentTool", XsdType::DATASETS }, + { "Ploidy", XsdType::DATASETS }, + { "ProdDist", XsdType::DATASETS }, + { "Provenance", XsdType::DATASETS }, + { "ReadLenDist", XsdType::DATASETS }, + { "ReadQualDist", XsdType::DATASETS }, + { "ReadTypeDist", XsdType::DATASETS }, + { "ReferenceSet", XsdType::DATASETS }, + { "ShortInsertFraction", XsdType::DATASETS }, + { "SubreadSet", XsdType::DATASETS }, + { "SummaryStats", XsdType::DATASETS }, + { "TotalLength", XsdType::DATASETS }, + { "TranscriptSet", XsdType::DATASETS }, + { "TranscriptAlignmentSet",XsdType::DATASETS }, + + // 'pbmeta' elements + // + { "Automation", XsdType::COLLECTION_METADATA }, + { "AutomationName", XsdType::COLLECTION_METADATA }, + { "CellIndex", XsdType::COLLECTION_METADATA }, + { "CellPac", XsdType::COLLECTION_METADATA }, + { "CollectionFileCopy", XsdType::COLLECTION_METADATA }, + { "CollectionMetadata", XsdType::COLLECTION_METADATA }, + { "CollectionNumber", XsdType::COLLECTION_METADATA }, + { "CollectionPathUri", XsdType::COLLECTION_METADATA }, + { "Collections", XsdType::COLLECTION_METADATA }, + { "Concentration", XsdType::COLLECTION_METADATA }, + { "ConfigFileName", XsdType::COLLECTION_METADATA }, + { "CopyFiles", XsdType::COLLECTION_METADATA }, + { "InstCtrlVer", XsdType::COLLECTION_METADATA }, + { "MetricsVerbosity", XsdType::COLLECTION_METADATA }, + { "Name", XsdType::COLLECTION_METADATA }, + { "OutputOptions", XsdType::COLLECTION_METADATA }, + { "PlateId", XsdType::COLLECTION_METADATA }, + { "Primary", XsdType::COLLECTION_METADATA }, + { "Readout", XsdType::COLLECTION_METADATA }, + { "ResultsFolder", XsdType::COLLECTION_METADATA }, + { "RunDetails", XsdType::COLLECTION_METADATA }, + { "RunId", XsdType::COLLECTION_METADATA }, + { "SampleReuseEnabled", XsdType::COLLECTION_METADATA }, + { "SequencingCondition", XsdType::COLLECTION_METADATA }, + { "SigProcVer", XsdType::COLLECTION_METADATA }, + { "SizeSelectionEnabled", XsdType::COLLECTION_METADATA }, + { "StageHotstartEnabled", XsdType::COLLECTION_METADATA }, + { "UseCount", XsdType::COLLECTION_METADATA }, + { "WellName", XsdType::COLLECTION_METADATA }, + { "WellSample", XsdType::COLLECTION_METADATA }, + + // 'pbsample' elements + // + { "BioSample", XsdType::SAMPLE_INFO }, + { "BioSamplePointer", XsdType::SAMPLE_INFO }, + { "BioSamplePointers", XsdType::SAMPLE_INFO }, + { "BioSamples", XsdType::SAMPLE_INFO } +}; +// clang-format on + +} // namespace internal + +// --------------- +// NamespaceInfo +// --------------- + +static_assert(std::is_copy_constructible::value, + "NamespaceInfo(const NamespaceInfo&) is not = default"); +static_assert(std::is_copy_assignable::value, + "NamespaceInfo& operator=(const NamespaceInfo&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "NamespaceInfo(NamespaceInfo&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +NamespaceInfo::NamespaceInfo(std::string name, std::string uri) + : name_{std::move(name)}, uri_{std::move(uri)} +{ +} + +const std::string& NamespaceInfo::Name() const { return name_; } + +const std::string& NamespaceInfo::Uri() const { return uri_; } + +// ------------------- +// NamespaceRegistry +// ------------------- + +static_assert(std::is_copy_constructible::value, + "NamespaceRegistry(const NamespaceRegistry&) is not = default"); +static_assert(std::is_copy_assignable::value, + "NamespaceRegistry& operator=(const NamespaceRegistry&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "NamespaceRegistry(NamespaceRegistry&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "NamespaceRegistry& operator=(NamespaceRegistry&&) is not = noexcept"); + +NamespaceRegistry::NamespaceRegistry() : data_{internal::DefaultRegistry()} {} + +const NamespaceInfo& NamespaceRegistry::DefaultNamespace() const { return Namespace(DefaultXsd()); } + +XsdType NamespaceRegistry::DefaultXsd() const { return defaultXsdType_; } + +const NamespaceInfo& NamespaceRegistry::Namespace(const XsdType& xsd) const +{ + return data_.at(xsd); +} + +void NamespaceRegistry::Register(const XsdType& xsd, const NamespaceInfo& namespaceInfo) +{ + data_[xsd] = namespaceInfo; +} + +void NamespaceRegistry::SetDefaultXsd(const XsdType& xsd) { defaultXsdType_ = xsd; } + +XsdType NamespaceRegistry::XsdForElement(const std::string& elementLabel) const +{ + const auto iter = internal::elementRegistry.find(elementLabel); + return (iter == internal::elementRegistry.cend() ? XsdType::NONE : iter->second); +} + +XsdType NamespaceRegistry::XsdForUri(const std::string& uri) const +{ + for (const auto& entry : data_) { + const auto& info = entry.second; + if (info.Uri() == uri) return entry.first; + } + return XsdType::NONE; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/EntireFileQuery.cpp b/src/EntireFileQuery.cpp new file mode 100644 index 0000000..85f65cf --- /dev/null +++ b/src/EntireFileQuery.cpp @@ -0,0 +1,34 @@ +// File Description +/// \file EntireFileQuery.cpp +/// \brief Implements the EntireFileQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/EntireFileQuery.h" + +#include "pbbam/CompositeBamReader.h" + +namespace PacBio { +namespace BAM { + +class EntireFileQuery::EntireFileQueryPrivate +{ +public: + EntireFileQueryPrivate(const DataSet &dataset) : reader_(dataset) {} + + SequentialCompositeBamReader reader_; +}; + +EntireFileQuery::EntireFileQuery(const DataSet &dataset) + : internal::IQuery(), d_(new EntireFileQueryPrivate(dataset)) +{ +} + +EntireFileQuery::~EntireFileQuery() = default; + +bool EntireFileQuery::GetNext(BamRecord &r) { return d_->reader_.GetNext(r); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/FaiIndex.cpp b/src/FaiIndex.cpp new file mode 100644 index 0000000..e59def1 --- /dev/null +++ b/src/FaiIndex.cpp @@ -0,0 +1,139 @@ +// File Description +/// \file FastaReader.cpp +/// \brief Implements the FastaReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FaiIndex.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "FaiIndex(const FaiIndex&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "FaiIndex& operator=(const FaiIndex&) is not = delete"); + +bool operator==(const FaiEntry& lhs, const FaiEntry& rhs) +{ + return std::tie(lhs.Length, lhs.SeqOffset, lhs.NumBases, lhs.NumBytes, lhs.QualOffset) == + std::tie(rhs.Length, rhs.SeqOffset, rhs.NumBases, rhs.NumBytes, rhs.QualOffset); +} + +std::ostream& operator<<(std::ostream& out, const FaiEntry& entry) +{ + out << entry.Length << '\t' << entry.SeqOffset << '\t' << entry.NumBases << '\t' + << entry.NumBytes; + if (entry.QualOffset >= 0) out << '\t' << entry.QualOffset; + return out; +} + +class FaiIndex::FaiIndexPrivate +{ +public: + FaiIndexPrivate() = default; + FaiIndexPrivate(const std::string& fn) { LoadFromFile(fn); } + + void Add(std::string name, FaiEntry entry) + { + names_.push_back(name); + data_.emplace(std::move(name), std::move(entry)); + } + + void LoadFromFile(const std::string& fn) + { + std::ifstream f{fn}; + std::string line; + std::vector fields; + while (std::getline(f, line)) { + + fields = Split(line, '\t'); + const auto numFields = fields.size(); + if (numFields < 5 || numFields > 6) { + std::ostringstream msg; + msg << "FaiIndex: malformatted index line, incorrect number of fields\n" + << " expected: 5 for FASTA, or 6 for FASTQ\n" + << " observed: " << numFields << " in line:\n" + << line << '\n'; + throw std::runtime_error{msg.str()}; + } + + FaiEntry entry; + entry.Length = std::stoull(fields[1]); + entry.SeqOffset = std::stoull(fields[2]); + entry.NumBases = std::stoul(fields[3]); + entry.NumBytes = std::stoul(fields[4]); + if (numFields == 6) entry.QualOffset = std::stoll(fields[5]); + + Add(std::move(fields[0]), std::move(entry)); + } + } + + std::vector names_; // save names in input order + std::unordered_map data_; // map name -> data +}; + +FaiIndex::FaiIndex(const std::string& fn) : d_{std::make_unique(fn)} {} + +FaiIndex::FaiIndex() : d_{std::make_unique()} {} + +FaiIndex::FaiIndex(FaiIndex&&) noexcept = default; + +FaiIndex& FaiIndex::operator=(FaiIndex&&) noexcept = default; + +FaiIndex::~FaiIndex() = default; + +void FaiIndex::Add(std::string name, FaiEntry entry) { d_->Add(std::move(name), std::move(entry)); } + +const FaiEntry& FaiIndex::Entry(const std::string& name) const +{ + const auto found = d_->data_.find(name); + if (found == d_->data_.cend()) + throw std::runtime_error{"FaiIndex: could not find entry for sequence name: " + name}; + return found->second; +} + +const FaiEntry& FaiIndex::Entry(const uint32_t row) const +{ + const auto& name = d_->names_.at(row); + return Entry(name); +} + +bool FaiIndex::HasEntry(const std::string& name) const +{ + const auto found = d_->data_.find(name); + return found != d_->data_.cend(); +} + +const std::vector& FaiIndex::Names() const { return d_->names_; } + +void FaiIndex::Save(const std::string& fn) const +{ + std::ofstream out{fn}; + Save(out); +} + +void FaiIndex::Save(std::ostream& out) const +{ + for (const auto& name : d_->names_) { + const auto& entry = Entry(name); + out << name << '\t' << entry << '\n'; + } +} + +} // namespace BAM +} // namespace PacBio \ No newline at end of file diff --git a/src/FaiZmwChunker.cpp b/src/FaiZmwChunker.cpp new file mode 100644 index 0000000..062b6f0 --- /dev/null +++ b/src/FaiZmwChunker.cpp @@ -0,0 +1,119 @@ +// File Description +/// \file FaiZmwChunker.cpp +/// \brief Implements the FaiZmwChunker class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "FaiZmwChunker.h" + +#include + +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { +namespace { + +int32_t HoleNumber(const std::string& name) +{ + const auto firstSlash = name.find('/'); + if (firstSlash == std::string::npos) + throw std::runtime_error{"FaiZmwChunker: could not parse hole number from name: " + name}; + + auto numberEnd = name.find('/', firstSlash + 1); + if (numberEnd == std::string::npos) numberEnd = name.size(); + + return std::stoi(name.substr(firstSlash + 1, (numberEnd - firstSlash))); +} + +} // namespace + +FaiZmwChunker::FaiZmwChunker(const FaiIndex& index, const size_t numChunks) +{ + // zero chunks is error + if (numChunks == 0) + throw std::runtime_error{"FaiZmwChunker: requested chunk count must be greater than zero"}; + + // empty index is not (?), but quick return + const auto& names = index.Names(); + if (names.empty()) return; + + // tease apart unique ZMWs + int32_t currentHoleNumber = -1; + std::vector rawChunks; + for (const auto& name : names) { + const int32_t holeNumber = HoleNumber(name); + if (holeNumber != currentHoleNumber) { + rawChunks.emplace_back(FaiZmwChunk{name, index.Entry(name).SeqOffset, 1, 1}); + currentHoleNumber = holeNumber; + } else + ++rawChunks.back().NumRecords; + } + + // no empty chunks (e.g. reduce the requested number, if small ZMW input) + const size_t actualNumChunks = std::min(numChunks, rawChunks.size()); + + // determine how many ZMWs should land in each chunk, spread roughly evenly + const int minimum = (rawChunks.size() / actualNumChunks); + const int modulo = (rawChunks.size() % actualNumChunks); + std::vector chunkCounts(actualNumChunks, minimum); + for (int i = 0; i < modulo; ++i) + ++chunkCounts.at(i); + + // collate zmw data into larger chunks + size_t begin = 0; + size_t end = 0; + for (const auto n : chunkCounts) { + + // shift end down for this chunk + end += n; + assert(end <= rawChunks.size()); + + // add data for this chunk + FaiZmwChunk result = rawChunks.at(begin); + result.NumZmws = n; + for (size_t j = begin + 1; j < end; ++j) + result.NumRecords += rawChunks.at(j).NumRecords; + chunks_.emplace_back(std::move(result)); + + // slide to next chunk + begin = end; + } +} + +FaiZmwChunker::FaiZmwChunker(const std::string& filename, const size_t numChunks) + : FaiZmwChunker{FaiIndex{filename}, numChunks} +{ +} + +FaiZmwChunker::FaiZmwChunker(const FaiZmwChunker&) = default; + +FaiZmwChunker::FaiZmwChunker(FaiZmwChunker&&) noexcept = default; + +FaiZmwChunker& FaiZmwChunker::operator=(const FaiZmwChunker&) = default; + +FaiZmwChunker& FaiZmwChunker::operator=(FaiZmwChunker&&) noexcept = default; + +FaiZmwChunker::~FaiZmwChunker() = default; + +const FaiZmwChunk& FaiZmwChunker::Chunk(size_t chunk) const { return chunks_.at(chunk); } + +size_t FaiZmwChunker::NumChunks() const { return chunks_.size(); } + +// size_t FaiZmwChunker::MaxChunkSize(size_t index) const +// { +// const auto max = std::max_element( +// chunks_.cbegin(), chunks_.cend(), +// [](const ZmwChunk& lhs, const ZmwChunk& rhs) { return lhs.NumZmws < rhs.NumZmws; }); + +// if (max == chunks_.cend()) return 0; +// return (*max).NumZmws; +// } + +} // namespace BAM +} // namespace PacBio diff --git a/src/FaiZmwChunker.h b/src/FaiZmwChunker.h new file mode 100644 index 0000000..5c52e03 --- /dev/null +++ b/src/FaiZmwChunker.h @@ -0,0 +1,84 @@ +// File Description +/// \file FaiZmwChunker.h +/// \brief Defines the FaiZmwChunker enum. +// +// Author: Derek Barnett + +#ifndef FAIZMWCHUNKER_H +#define FAIZMWCHUNKER_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/FaiIndex.h" + +namespace PacBio { +namespace BAM { + +struct FaiZmwChunk +{ + /// Name of first entry + std::string FirstSeqName; + + /// File offset to the sequence of the chunk's first entry. + uint64_t FirstSeqOffset; + + // Total number of records in chunk. + size_t NumRecords; + + // Number of unique ZMWs + size_t NumZmws; +}; + +/// +/// \brief The FaiZmwChunker takes a FAI index and bins unique ZMW hole numbers +/// into chunks. +/// +class FaiZmwChunker +{ +public: + /// + /// \brief Construct a new FaiZmwChunker + /// + /// \param index FAI index + /// \param numChunks desired number of chunks + /// + /// Actual chunk count may be smaller than the requested number, if the input + /// size is smaller. + /// + FaiZmwChunker(const FaiIndex& index, const size_t numChunks); + + /// + /// \brief Construct a new FaiZmwChunker + /// + /// \param filename FAI filename + /// \param numChunks desired number of chunks + /// + /// Actual chunk count may be smaller than the requested number, if the input + /// size is smaller. + /// + FaiZmwChunker(const std::string& filename, const size_t numChunks); + + FaiZmwChunker(const FaiZmwChunker&); + FaiZmwChunker(FaiZmwChunker&&) noexcept; + FaiZmwChunker& operator=(const FaiZmwChunker&); + FaiZmwChunker& operator=(FaiZmwChunker&&) noexcept; + ~FaiZmwChunker(); + +public: + const FaiZmwChunk& Chunk(size_t chunk) const; + + size_t NumChunks() const; + + // size_t MaxChunkSize(size_t index) const; + +private: + std::vector chunks_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FAIZMWCHUNKER_H diff --git a/src/FastaCache.cpp b/src/FastaCache.cpp new file mode 100644 index 0000000..0eb50b2 --- /dev/null +++ b/src/FastaCache.cpp @@ -0,0 +1,61 @@ +#include "PbbamInternalConfig.h" + +#include "pbbam/FastaCache.h" + +#include + +#include "pbbam/FastaReader.h" + +namespace PacBio { +namespace BAM { + +FastaCacheData::FastaCacheData(const std::string& filename) : cache_{FastaReader::ReadAll(filename)} +{ + for (size_t i = 0; i < cache_.size(); ++i) + lookup_.emplace(cache_[i].Name(), i); +} + +std::string FastaCacheData::Subsequence(const std::string& name, size_t begin, size_t end) const +{ + const auto found = lookup_.find(name); + if (found == lookup_.cend()) { + std::string msg = "Could not find '"; + msg += name; + msg += "' in FastaCacheData::Subsequence()"; + throw std::runtime_error{msg}; + } + const std::string& seq = cache_[found->second].Bases(); + + if (begin > end) throw std::runtime_error{"begin > end in FastaCacheData::Subsequence"}; + const size_t length = end - begin; + return seq.substr(begin, length); +} + +std::vector FastaCacheData::Names() const +{ + std::vector result; + result.reserve(cache_.size()); + for (const auto& seq : cache_) + result.push_back(seq.Name()); + return result; +} + +size_t FastaCacheData::SequenceLength(const std::string& name) const +{ + const auto found = lookup_.find(name); + if (found == lookup_.cend()) { + std::string msg = "Could not find '"; + msg += name; + msg += "' in FastaCacheData::SequenceLength()"; + throw std::runtime_error{msg}; + } + return cache_[found->second].Bases().size(); +} + +FastaCache MakeFastaCache(const std::string& filename) +{ + return std::make_shared(filename); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/FastaReader.cpp b/src/FastaReader.cpp new file mode 100644 index 0000000..5bfca33 --- /dev/null +++ b/src/FastaReader.cpp @@ -0,0 +1,79 @@ +// File Description +/// \file FastaReader.cpp +/// \brief Implements the FastaReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FastaReader.h" + +#include +#include +#include +#include +#include +#include + +#include "pbbam/FormatUtils.h" + +#include "KSeqReader.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "FastaReader(const FastaReader&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "FastaReader& operator=(const FastaReader&) is not = delete"); + +class FastaReader::FastaReaderPrivate +{ +public: + explicit FastaReaderPrivate(const std::string& fn) + { + // validate extension + if (!FormatUtils::IsFastaFilename(fn)) { + throw std::runtime_error{"FastaReader: filename '" + fn + + "' is not recognized as a FASTA file."}; + } + reader_ = std::make_unique(fn); + } + + bool GetNext(FastaSequence& record) + { + const auto readOk = reader_->ReadNext(); + if (!readOk) return false; // not error, could be EOF + + record = FastaSequence{reader_->Name(), reader_->Bases()}; + return true; + } + + std::unique_ptr reader_; +}; + +FastaReader::FastaReader(const std::string& fn) + : internal::QueryBase{}, d_{std::make_unique(fn)} +{ +} + +FastaReader::FastaReader(FastaReader&&) noexcept = default; + +FastaReader& FastaReader::operator=(FastaReader&&) noexcept = default; + +FastaReader::~FastaReader() = default; + +bool FastaReader::GetNext(FastaSequence& record) { return d_->GetNext(record); } + +std::vector FastaReader::ReadAll(const std::string& fn) +{ + std::vector result; + result.reserve(256); + FastaReader reader{fn}; + for (const auto& seq : reader) + result.emplace_back(seq); + return result; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/FastaSequence.cpp b/src/FastaSequence.cpp new file mode 100644 index 0000000..9be2696 --- /dev/null +++ b/src/FastaSequence.cpp @@ -0,0 +1,61 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FastaSequence.h" + +#include + +#include +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +static_assert(std::is_copy_constructible::value, + "FastaSequence(const FastaSequence&) is not = default"); +static_assert(std::is_copy_assignable::value, + "FastaSequence& operator=(const FastaSequence&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "FastaSequence(FastaSequence&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +FastaSequence::FastaSequence(std::string name, std::string bases) + : name_{std::move(name)}, bases_{std::move(bases)} +{ + boost::algorithm::trim(name_); + boost::algorithm::trim(bases_); +} + +const std::string& FastaSequence::Bases() const { return bases_; } + +FastaSequence& FastaSequence::Bases(std::string bases) +{ + bases_ = std::move(bases); + return *this; +} + +const std::string& FastaSequence::Name() const { return name_; } + +FastaSequence& FastaSequence::Name(std::string name) +{ + name_ = std::move(name); + return *this; +} + +bool FastaSequence::operator==(const FastaSequence& other) const +{ + return std::tie(name_, bases_) == std::tie(other.name_, other.bases_); +} + +bool FastaSequence::operator!=(const FastaSequence& other) const { return !(*this == other); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/FastaSequenceQuery.cpp b/src/FastaSequenceQuery.cpp new file mode 100644 index 0000000..e865c3d --- /dev/null +++ b/src/FastaSequenceQuery.cpp @@ -0,0 +1,34 @@ +// File Description +/// \file FastaSequenceQuery.cpp +/// \brief Implements the FastaSequenceQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FastaSequenceQuery.h" + +#include "pbbam/CompositeFastaReader.h" + +namespace PacBio { +namespace BAM { + +class FastaSequenceQuery::FastaSequenceQueryPrivate +{ +public: + FastaSequenceQueryPrivate(const DataSet& dataset) : reader_{dataset} {} + + CompositeFastaReader reader_; +}; + +FastaSequenceQuery::FastaSequenceQuery(const DataSet& dataset) + : internal::QueryBase(), d_{std::make_unique(dataset)} +{ +} + +FastaSequenceQuery::~FastaSequenceQuery() = default; + +bool FastaSequenceQuery::GetNext(FastaSequence& seq) { return d_->reader_.GetNext(seq); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/FastaWriter.cpp b/src/FastaWriter.cpp new file mode 100644 index 0000000..4761527 --- /dev/null +++ b/src/FastaWriter.cpp @@ -0,0 +1,45 @@ +// File Description +/// \file FastaWriter.cpp +/// \brief Implements the FastaWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FastaWriter.h" + +#include + +#include "pbbam/BamRecord.h" +#include "pbbam/FastqSequence.h" +#include "pbbam/FormatUtils.h" +namespace PacBio { +namespace BAM { + +FastaWriter::FastaWriter(const std::string& fn) : IFastaWriter{} +{ + if (!FormatUtils::IsFastaFilename(fn)) { + throw std::runtime_error{"FastaReader: filename '" + fn + + "' is not recognized as a FASTA file."}; + } + + file_.open(fn); + if (!file_) throw std::runtime_error{"FastaWriter: could not open file for writing: " + fn}; +} + +void FastaWriter::TryFlush() { file_.flush(); } + +void FastaWriter::Write(const BamRecordImpl& bam) { Write(bam.Name(), bam.Sequence()); } + +void FastaWriter::Write(const FastaSequence& fastq) { Write(fastq.Name(), fastq.Bases()); } + +void FastaWriter::Write(const BamRecord& bam) { Write(bam.FullName(), bam.Sequence()); } + +void FastaWriter::Write(const std::string& name, const std::string& bases) +{ + // TODO: wrap bases + file_ << ">" << name << '\n' << bases << '\n'; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/FastqReader.cpp b/src/FastqReader.cpp new file mode 100644 index 0000000..8762edd --- /dev/null +++ b/src/FastqReader.cpp @@ -0,0 +1,76 @@ +// File Description +/// \file FastqReader.cpp +/// \brief Implements the FastqReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FastqReader.h" + +#include +#include +#include + +#include "pbbam/FormatUtils.h" + +#include "KSeqReader.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "FastqReader(const FastqReader&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "FastqReader& operator=(const FastqReader&) is not = delete"); + +class FastqReader::FastqReaderPrivate +{ +public: + explicit FastqReaderPrivate(const std::string& fn) + { + // validate extension + if (!FormatUtils::IsFastqFilename(fn)) { + throw std::runtime_error{"FastqReader: filename '" + fn + + "' is not recognized as a FASTQ file."}; + } + reader_ = std::make_unique(fn); + } + + bool GetNext(FastqSequence& record) + { + const auto ok = reader_->ReadNext(); + if (!ok) return false; // not error, could be EOF + + record = FastqSequence{reader_->Name(), reader_->Bases(), reader_->Qualities()}; + return true; + } + + std::unique_ptr reader_; +}; + +FastqReader::FastqReader(const std::string& fn) + : internal::QueryBase{}, d_{std::make_unique(fn)} +{ +} + +FastqReader::FastqReader(FastqReader&&) noexcept = default; + +FastqReader& FastqReader::operator=(FastqReader&&) noexcept = default; + +FastqReader::~FastqReader() = default; + +bool FastqReader::GetNext(FastqSequence& record) { return d_->GetNext(record); } + +std::vector FastqReader::ReadAll(const std::string& fn) +{ + std::vector result; + result.reserve(256); + FastqReader reader{fn}; + for (const auto& seq : reader) + result.emplace_back(seq); + return result; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/FastqSequence.cpp b/src/FastqSequence.cpp new file mode 100644 index 0000000..c70efe5 --- /dev/null +++ b/src/FastqSequence.cpp @@ -0,0 +1,55 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FastqSequence.h" + +#include +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +static_assert(std::is_copy_constructible::value, + "FastqSequence(const FastqSequence&) is not = default"); +static_assert(std::is_copy_assignable::value, + "FastqSequence& operator=(const FastqSequence&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "FastqSequence(FastqSequence&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +FastqSequence::FastqSequence(std::string name, std::string bases, Data::QualityValues qualities) + : FastaSequence{std::move(name), std::move(bases)}, qualities_{std::move(qualities)} +{ +} + +FastqSequence::FastqSequence(std::string name, std::string bases, std::string qualities) + : FastaSequence{std::move(name), std::move(bases)} + , qualities_{Data::QualityValues::FromFastq(qualities)} +{ +} + +const Data::QualityValues& FastqSequence::Qualities() const { return qualities_; } + +FastqSequence& FastqSequence::Qualities(QualityValues quals) +{ + qualities_ = std::move(quals); + return *this; +} + +bool FastqSequence::operator==(const FastqSequence& other) const +{ + return std::tie(Name(), Bases(), qualities_) == + std::tie(other.Name(), other.Bases(), other.qualities_); +} + +bool FastqSequence::operator!=(const FastqSequence& other) const { return !(*this == other); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/FastqWriter.cpp b/src/FastqWriter.cpp new file mode 100644 index 0000000..529fa98 --- /dev/null +++ b/src/FastqWriter.cpp @@ -0,0 +1,70 @@ +// File Description +/// \file FastqWriter.cpp +/// \brief Implements the FastqWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FastqWriter.h" + +#include + +#include "pbbam/BamRecord.h" +#include "pbbam/FastqSequence.h" +#include "pbbam/FormatUtils.h" +#include "pbbam/QualityValues.h" + +namespace PacBio { +namespace BAM { + +FastqWriter::FastqWriter(const std::string& fn) : IFastqWriter{} +{ + if (!FormatUtils::IsFastqFilename(fn)) { + throw std::runtime_error{"FastqReader: filename '" + fn + + "' is not recognized as a FASTQ file."}; + } + + file_.open(fn); + if (!file_) throw std::runtime_error{"FastqWriter: could not open file for writing: " + fn}; +} + +void FastqWriter::TryFlush() { file_.flush(); } + +void FastqWriter::Write(const FastqSequence& fastq) +{ + Write(fastq.Name(), fastq.Bases(), fastq.Qualities()); +} + +void FastqWriter::Write(const BamRecord& bam) +{ + Write(bam.FullName(), bam.Sequence(), bam.Qualities()); +} + +void FastqWriter::Write(const BamRecordImpl& bam) +{ + Write(bam.Name(), bam.Sequence(), bam.Qualities()); +} + +void FastqWriter::Write(const std::string& name, const std::string& bases, + const Data::QualityValues& quals) +{ + Write(name, bases, quals.Fastq()); +} + +void FastqWriter::Write(const std::string& name, const std::string& bases, const std::string& quals) +{ + file_ << "@" << name << '\n' << bases << '\n' << "+\n"; + + if (!quals.empty()) + file_ << quals; + else { + std::string q(bases.size(), '!'); + file_ << q; + } + + file_ << '\n'; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/FileProducer.cpp b/src/FileProducer.cpp new file mode 100644 index 0000000..ccdc218 --- /dev/null +++ b/src/FileProducer.cpp @@ -0,0 +1,43 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "FileProducer.h" + +#include + +#include + +namespace PacBio { +namespace BAM { + +FileProducer::FileProducer(std::string targetFilename) + : FileProducer(targetFilename, targetFilename + ".tmp") +{ +} + +FileProducer::FileProducer(std::string targetFilename, std::string tempFilename) + : targetFilename_{std::move(targetFilename)}, tempFilename_{std::move(tempFilename)} +{ + if (targetFilename_.empty()) { + throw std::runtime_error{"FileProducer error: cannot write to file with empty name"}; + } + + // override renaming if writing to stdout + // + // setting temp filename to '-' keeps consistent interfaces + // for derived classes to actually operate on temp filename + if (targetFilename_ == "-") tempFilename_ = "-"; +} + +FileProducer::~FileProducer() +{ + // skip renaming if there is a 'live' exception + // or if writing to stdout + if ((std::current_exception() == nullptr) && (tempFilename_ != "-")) { + std::rename(tempFilename_.c_str(), targetFilename_.c_str()); + } +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/FileProducer.h b/src/FileProducer.h new file mode 100644 index 0000000..2562350 --- /dev/null +++ b/src/FileProducer.h @@ -0,0 +1,56 @@ +// Author: Derek Barnett + +#ifndef FILEPRODUCER_H +#define FILEPRODUCER_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +// The FileProducer class provides functionality for working with a temp +// file until successful destruction of a FileProducer-derived class. +// +// Derived classes should be sure to flush/close the temp file, and the +// FileProducer's destructor will ensure that the temp file will be renamed to +// the target filename. +// +// If destruction is triggered by an exception, no renaming will occur. +// +class FileProducer +{ +public: + FileProducer() = delete; + + // Initializes FileProducer with specified target filename. Temp filename is + // set to target filename plus ".tmp" suffix. + explicit FileProducer(std::string targetFilename); + + // Initializes FileProducer with specified target filename & explicit temp + // filename. + FileProducer(std::string targetFilename, std::string tempFilename); + + // Renames temp file to target filename. + // + // Derived classes should ensure that data is flushed and file handle closed + // before or during their destructor. + // + // Remaming will not occur if there is a 'live' exception being thrown. + // + virtual ~FileProducer(); + + const std::string& TargetFilename() const { return targetFilename_; } + const std::string& TempFilename() const { return tempFilename_; } + +private: + std::string targetFilename_; + std::string tempFilename_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FILEPRODUCER_H diff --git a/src/FileUtils.cpp b/src/FileUtils.cpp new file mode 100644 index 0000000..8f3d848 --- /dev/null +++ b/src/FileUtils.cpp @@ -0,0 +1,203 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "FileUtils.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { + +namespace { + +// pops "file://" scheme off the front of a URI/filepath, if found +static std::string removeFileUriScheme(const std::string& uri) +{ + assert(!uri.empty()); + + auto schemeLess = uri; + const auto fileScheme = std::string{"file://"}; + const auto schemeFound = schemeLess.find(fileScheme); + if (schemeFound != std::string::npos) { + if (schemeFound != 0) + throw std::runtime_error{"FileUtils: malformed URI, scheme is not at beginning"}; + schemeLess = schemeLess.substr(fileScheme.size()); + } + return schemeLess; +} + +#ifdef PBBAM_WIN_FILEPATHS + +static std::string removeDiskName(const std::string& filePath) +{ + if (filePath.size() >= 2) { + const char firstChar = filePath.at(0); + if ((isalpha(firstChar) != 0) && (filePath.at(1) == ':')) return filePath.substr(2); + } + return filePath; +} + +static const char native_pathSeparator = '\\'; + +static bool native_pathIsAbsolute(const std::string& filePath) +{ + assert(!filePath.empty()); + + // if starts with single slash or double slash + if (boost::algorithm::starts_with(filePath, "\\")) return true; + + // if starts with single or double-dots -> not absolute + if (boost::algorithm::starts_with(filePath, ".")) return false; + + // if starts with disk drive name and colon ("C:\foo\bar.txt") + // strip the drive name and check to see if the remaining path is absolute + if (filePath.size() >= 2) { + const char firstChar = filePath.at(0); + if ((isalpha(firstChar) != 0) && (filePath.at(1) == ':')) + return native_pathIsAbsolute(removeDiskName(filePath)); + } + + // otherwise, likely relative + return false; +} + +static std::string native_resolvedFilePath(const std::string& filePath, const std::string& from) +{ + // strip file:// scheme if present + auto schemeLess = removeFileUriScheme(filePath); + + // if empty or already absolute path, just return it + // upfront empty check simplifies further parsing logic + if (schemeLess.empty() || native_pathIsAbsolute(schemeLess)) return schemeLess; + + // else make relative from the provided 'from' directory + // + // first pop disk name, then any leading single-dot '.' + // + // since we're prepending the 'from' directory, we can remove + // any leading './' form our file path. this may just mean that + // we pop it off to add it right back (when from == '.'), but this + // keeps it consistent with other 'from' parent directories + // + schemeLess = removeDiskName(schemeLess); + + const bool thisDirAtStart = (schemeLess.find(".") == 0); + if (thisDirAtStart) { + if (schemeLess.find(native_pathSeparator) == 1) schemeLess = schemeLess.substr(2); + } + return from + native_pathSeparator + schemeLess; +} + +#else // else for non-Windows systems + +static const char native_pathSeparator = '/'; + +static bool native_pathIsAbsolute(const std::string& filePath) { return filePath.at(0) == '/'; } + +static std::string native_resolvedFilePath(const std::string& filePath, const std::string& from) +{ + // strip file:// scheme if present + auto schemeLess = removeFileUriScheme(filePath); + + // if empty or already absolute path, just return it + // upfront empty check simplifies further parsing logic + if (schemeLess.empty() || native_pathIsAbsolute(schemeLess)) return schemeLess; + + // else make relative from the provided 'from' directory + // + // since we're prepending the 'from' directory, we can remove + // any leading './' form our file path. this may just mean that + // we pop it off to add it right back (when from == '.'), but this + // keeps it consistent with other 'from' parent directories + // + const bool thisDirAtStart = (schemeLess.find(".") == 0); + if (thisDirAtStart) { + if (schemeLess.find(native_pathSeparator) == 1) schemeLess = schemeLess.substr(2); + } + return from + native_pathSeparator + schemeLess; +} + +#endif // PBBAM_WIN_FILEPATHS + +} // anonymous + +// see http://stackoverflow.com/questions/2869594/how-return-a-stdstring-from-cs-getcwd-function +std::string FileUtils::CurrentWorkingDirectory() +{ + const size_t chunkSize = 1024; + const size_t maxNumChunks = 20; + + // stack-based buffer for 'normal' case + char buffer[chunkSize]; + if (getcwd(buffer, sizeof(buffer)) != nullptr) return std::string(buffer); + + // if error is not ERANGE, then it's not a problem of too-long name... something else happened + if (errno != ERANGE) + throw std::runtime_error{"FileUtils: could not determine current working directory path"}; + + // long path - use heap, trying progressively longer buffers + for (size_t chunks = 2; chunks < maxNumChunks; ++chunks) { + std::unique_ptr cwd(new char[chunkSize * chunks]); + if (getcwd(cwd.get(), chunkSize * chunks) != nullptr) return std::string(cwd.get()); + + // if error is not ERANGE, then it's not a problem of too-long name... something else happened + if (errno != ERANGE) + throw std::runtime_error{ + "FileUtils: could not determine current working directory path"}; + } + + // crazy long path name + throw std::runtime_error{ + "FileUtils: could not determine current working directory - extremely long path"}; +} + +std::string FileUtils::DirectoryName(const std::string& file) +{ + const auto found = file.rfind(Separator(), file.length()); + if (found != std::string::npos) return file.substr(0, found); + return std::string("."); +} + +bool FileUtils::Exists(const char* fn) +{ + struct stat buf; + return (stat(fn, &buf) != -1); +} + +std::chrono::system_clock::time_point FileUtils::LastModified(const char* fn) +{ + struct stat s; + if (stat(fn, &s) != 0) + throw std::runtime_error{"FileUtils: could not get timestamp for file: " + std::string{fn}}; + return std::chrono::system_clock::from_time_t(s.st_mtime); +} + +std::string FileUtils::ResolvedFilePath(const std::string& filePath, const std::string& from) +{ + return native_resolvedFilePath(filePath, from); +} + +constexpr char FileUtils::Separator() { return native_pathSeparator; } + +off_t FileUtils::Size(const char* fn) +{ + struct stat s; + if (stat(fn, &s) != 0) + throw std::runtime_error{"FileUtils: could not determine size of file: " + std::string{fn}}; + return s.st_size; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/FileUtils.h b/src/FileUtils.h new file mode 100644 index 0000000..dc9d2dd --- /dev/null +++ b/src/FileUtils.h @@ -0,0 +1,108 @@ +// Author: Derek Barnett + +#ifndef FILEUTILS_H +#define FILEUTILS_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +class FileUtils +{ +public: + /// \returns application's current working directory + static std::string CurrentWorkingDirectory(); + + /// Parses a filepath for the the directory name for a file. + /// + /// Essentially this method strips the filename from the string provided (/path/to/file => /path/to). + /// If only a filename is provided, then "." is returned to indicate the current directory. + /// + /// \param[in] file name of file (can be just a filename or path/to/filename) + /// \returns file's directory name + /// + static std::string DirectoryName(const std::string& file); + + /// Check for existence of a file. + /// + /// \param[in] fn full path to file + /// \returns true if file exists & can be opened + /// + static bool Exists(const char* fn); + + /// Check for existence of a file. + /// + /// \param[in] fn full path to file + /// \returns true if file exists & can be opened + /// + static bool Exists(const std::string& fn); + + /// Check "last modified" timestamp for a file. + /// + /// \param[in] fn full path to file + /// \returns time of last modification + /// \throws runtime_error if file info can't be accessed + /// + static std::chrono::system_clock::time_point LastModified(const char* fn); + + /// Check "last modified" timestamp for a file. + /// + /// \param[in] fn full path to file + /// \returns time of last modification + /// \throws runtime_error if file info can't be accessed + /// + static std::chrono::system_clock::time_point LastModified(const std::string& fn); + + /// Resolves input file path using optional starting directory. + /// + /// \verbatim + /// /absolute/path/to/file.txt => /absolute/path/to/file.txt + /// ../relative/path/to/file.txt => /../relative/path/to/file.txt + /// file.txt => /file.txt + /// \endverbatim + /// + /// \note This method will strip any URI scheme as well ("file://") so that the result is immediately ready from I/O operations. + /// + /// \param[in] filePath file path to be resolved + /// \param[in] from optional starting directory (useful if not same as application's working directory) + /// \returns resolved file path + /// + static std::string ResolvedFilePath(const std::string& filePath, const std::string& from = "."); + + /// \returns native path separator + constexpr static char Separator(); + + /// Check size of file. + /// + /// \param[in] fn full path to file + /// \returns file size in bytes + /// \throws runtime_error if file info can't be accessed + /// + static off_t Size(const char* fn); + + /// Check size of file. + /// + /// \param[in] fn full path to file + /// \returns file size in bytes + /// \throws runtime_error if file info can't be accessed + /// + static off_t Size(const std::string& fn); +}; + +inline bool FileUtils::Exists(const std::string& fn) { return FileUtils::Exists(fn.c_str()); } + +inline std::chrono::system_clock::time_point FileUtils::LastModified(const std::string& fn) +{ + return FileUtils::LastModified(fn.c_str()); +} + +inline off_t FileUtils::Size(const std::string& fn) { return FileUtils::Size(fn.c_str()); } + +} // namespace BAM +} // namespace PacBio + +#endif // FILEUTILS_H diff --git a/src/FofnReader.cpp b/src/FofnReader.cpp new file mode 100644 index 0000000..a8ae80d --- /dev/null +++ b/src/FofnReader.cpp @@ -0,0 +1,22 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "FofnReader.h" + +#include + +namespace PacBio { +namespace BAM { + +std::vector FofnReader::Files(std::istream& in) +{ + std::vector files; + std::string fn; + while (std::getline(in, fn)) + files.push_back(fn); + return files; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/FofnReader.h b/src/FofnReader.h new file mode 100644 index 0000000..2b2d441 --- /dev/null +++ b/src/FofnReader.h @@ -0,0 +1,26 @@ +// Author: Derek Barnett + +#ifndef FOFNREADER_H +#define FOFNREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +class FofnReader +{ +public: + static std::vector Files(std::istream& in); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // FOFNREADER_H diff --git a/src/FormatUtils.cpp b/src/FormatUtils.cpp new file mode 100644 index 0000000..7b33e33 --- /dev/null +++ b/src/FormatUtils.cpp @@ -0,0 +1,61 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/FormatUtils.h" + +#include + +#include + +#include "MemoryUtils.h" + +namespace PacBio { +namespace BAM { + +const std::vector& FormatUtils::BedExtensions() +{ + static const std::vector extensions{"bed", "bed.gz"}; + return extensions; +} + +const std::vector& FormatUtils::FastaExtensions() +{ + static const std::vector extensions{"fa", "fasta", "fa.gz", "fasta.gz"}; + return extensions; +} + +const std::vector& FormatUtils::FastqExtensions() +{ + static const std::vector extensions{"fq", "fastq", "fq.gz", "fastq.gz"}; + return extensions; +} + +HtslibCompression FormatUtils::CompressionType(BGZF* bgzf) +{ + return static_cast(bgzf_compression(bgzf)); +} + +HtslibCompression FormatUtils::CompressionType(const std::string& fn) +{ + std::unique_ptr bgzf(bgzf_open(fn.c_str(), "rb")); + if (bgzf == nullptr) throw std::runtime_error{"could not check compression level for: " + fn}; + return CompressionType(bgzf.get()); +} + +bool FormatUtils::IsBedFilename(const std::string& fn) { return IsFormat(fn, BedExtensions()); } + +bool FormatUtils::IsFastaFilename(const std::string& fn) { return IsFormat(fn, FastaExtensions()); } + +bool FormatUtils::IsFastqFilename(const std::string& fn) { return IsFormat(fn, FastqExtensions()); } + +bool FormatUtils::IsFormat(const std::string& fn, const std::vector& extensions) +{ + const auto found = std::find_if( + extensions.cbegin(), extensions.cend(), + [&fn](const std::string& ext) { return boost::algorithm::iends_with(fn, ext); }); + return found != extensions.cend(); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/GenomicIntervalQuery.cpp b/src/GenomicIntervalQuery.cpp new file mode 100644 index 0000000..78ecef6 --- /dev/null +++ b/src/GenomicIntervalQuery.cpp @@ -0,0 +1,70 @@ +// File Description +/// \file GenomicIntervalQuery.cpp +/// \brief Implements the GenomicIntervalQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/GenomicIntervalQuery.h" + +#include "pbbam/CompositeBamReader.h" +#include "pbbam/DataSet.h" +#include "pbbam/GenomicInterval.h" + +namespace PacBio { +namespace BAM { + +class GenomicIntervalQuery::GenomicIntervalQueryPrivate +{ +public: + GenomicIntervalQueryPrivate(const DataSet& dataset, const BaiIndexCache& cache) + : reader_{dataset, cache} + { + } + + GenomicIntervalQueryPrivate(const GenomicInterval& interval, const DataSet& dataset, + const BaiIndexCache& cache) + : reader_{interval, dataset, cache} + { + } + + GenomicIntervalCompositeBamReader reader_; +}; + +GenomicIntervalQuery::GenomicIntervalQuery(const DataSet& dataset) + : GenomicIntervalQuery(dataset, MakeBaiIndexCache(dataset)) +{ +} + +GenomicIntervalQuery::GenomicIntervalQuery(const DataSet& dataset, const BaiIndexCache& cache) + : internal::IQuery(), d_{std::make_unique(dataset, cache)} +{ +} + +GenomicIntervalQuery::GenomicIntervalQuery(const GenomicInterval& interval, const DataSet& dataset) + : GenomicIntervalQuery(interval, dataset, MakeBaiIndexCache(dataset)) +{ +} + +GenomicIntervalQuery::GenomicIntervalQuery(const GenomicInterval& interval, const DataSet& dataset, + const BaiIndexCache& cache) + : internal::IQuery() + , d_{std::make_unique(interval, dataset, cache)} +{ +} + +GenomicIntervalQuery::~GenomicIntervalQuery() = default; + +bool GenomicIntervalQuery::GetNext(BamRecord& r) { return d_->reader_.GetNext(r); } + +GenomicIntervalQuery& GenomicIntervalQuery::Interval(const GenomicInterval& interval) +{ + d_->reader_.Interval(interval); + return *this; +} + +const GenomicInterval& GenomicIntervalQuery::Interval() const { return d_->reader_.Interval(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/IFastaWriter.cpp b/src/IFastaWriter.cpp new file mode 100644 index 0000000..dd0c194 --- /dev/null +++ b/src/IFastaWriter.cpp @@ -0,0 +1,19 @@ +// File Description +/// \file IFastaWriter.cpp +/// \brief Implements the IFastaWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/IFastaWriter.h" + +namespace PacBio { +namespace BAM { + +IFastaWriter::IFastaWriter() = default; + +IFastaWriter::~IFastaWriter() = default; + +} // namespace BAM +} // namespace PacBio diff --git a/src/IFastqWriter.cpp b/src/IFastqWriter.cpp new file mode 100644 index 0000000..c294cdb --- /dev/null +++ b/src/IFastqWriter.cpp @@ -0,0 +1,19 @@ +// File Description +/// \file IFastqWriter.cpp +/// \brief Implements the IFastqWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/IFastqWriter.h" + +namespace PacBio { +namespace BAM { + +IFastqWriter::IFastqWriter() = default; + +IFastqWriter::~IFastqWriter() = default; + +} // namespace BAM +} // namespace PacBio diff --git a/src/IRecordWriter.cpp b/src/IRecordWriter.cpp new file mode 100644 index 0000000..5931f78 --- /dev/null +++ b/src/IRecordWriter.cpp @@ -0,0 +1,19 @@ +// File Description +/// \file IRecordWriter.cpp +/// \brief Implements the IRecordWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/IRecordWriter.h" + +namespace PacBio { +namespace BAM { + +IRecordWriter::IRecordWriter() = default; + +IRecordWriter::~IRecordWriter() = default; + +} // namespace BAM +} // namespace PacBio diff --git a/src/IndexedBamWriter.cpp b/src/IndexedBamWriter.cpp new file mode 100644 index 0000000..89de02b --- /dev/null +++ b/src/IndexedBamWriter.cpp @@ -0,0 +1,1032 @@ +/// File Description +/// \file IndexedBamWriter.cpp +/// \brief Implements the IndexedBamWriter class +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/IndexedBamWriter.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/BamRecordImpl.h" +#include "pbbam/BamWriter.h" +#include "pbbam/PbiRawData.h" +#include "pbbam/RecordType.h" +#include "pbbam/Unused.h" +#include "pbbam/Validator.h" + +#include "FileProducer.h" +#include "MemoryUtils.h" + +namespace PacBio { +namespace BAM { +namespace internal { + +void bgzf_write_safe2(BGZF* fp, const void* data, size_t length) +{ + const auto ret = bgzf_write(fp, data, length); + if (ret < 0L) + throw std::runtime_error{ + "IndexedBamWriter: non-zero returned from bgzf_write(). Out of disk space?"}; +} + +struct GzIndexEntry +{ + int64_t vAddress; + int64_t uAddress; +}; + +template +inline void SwapEndianness2(std::vector& data) +{ + constexpr const size_t elementSize = sizeof(T); + const size_t numReads = data.size(); + switch (elementSize) { + case 1: + break; // no swapping necessary + case 2: + for (size_t i = 0; i < numReads; ++i) + ed_swap_2p(&data[i]); + break; + case 4: + for (size_t i = 0; i < numReads; ++i) + ed_swap_4p(&data[i]); + break; + case 8: + for (size_t i = 0; i < numReads; ++i) + ed_swap_8p(&data[i]); + break; + default: + throw std::runtime_error{"IndexedBamWriter: unsupported element size: " + + std::to_string(elementSize)}; + } +} + +template +inline void WriteBgzfVector2(BGZF* fp, std::vector& data) +{ + assert(fp); + if (fp->is_be) SwapEndianness2(data); + bgzf_write_safe2(fp, data.data(), data.size() * sizeof(T)); +} + +struct PbiFieldBlock2 +{ + int64_t pos_; // file position of block start + size_t n_; // number of entries in block +}; + +template +class PbiField2 +{ + constexpr static const size_t ElementSize = sizeof(T); + +public: + PbiField2(size_t maxBufferSize) : maxElementCount_{maxBufferSize / ElementSize} + { + buffer_.reserve(maxElementCount_); + } + + void Add(T value) { buffer_.push_back(value); } + bool IsFull() const { return buffer_.size() == maxElementCount_; } + + size_t maxElementCount_; + std::vector buffer_; + std::vector blocks_; +}; + +class PbiReferenceDataBuilder2 +{ +public: + using ReferenceRows = std::pair; // [startRow, endRow) + + explicit PbiReferenceDataBuilder2(const size_t numReferenceSequences) + { + // initialize with number of references we expect to see + // + // we can add more later, but want to ensure known references have an entry + // even if no records are observed mapping to it + // + for (size_t i = 0; i < numReferenceSequences; ++i) + rawReferenceEntries_[i] = PbiReferenceEntry(i); + + // also create an "unmapped" entry + rawReferenceEntries_[PbiReferenceEntry::UNMAPPED_ID] = PbiReferenceEntry{}; + } + + bool AddRecord(const BamRecord& record, const int32_t rowNumber) + { + // fetch ref ID & pos for record + const int32_t tId = record.ReferenceId(); + const int32_t pos = record.ReferenceStart(); + + // sanity checks to protect against non-coordinate-sorted BAMs + if (lastRefId_ != tId || (lastRefId_ >= 0 && tId < 0)) { + if (tId >= 0) { + + // if we've already seen unmapped reads, but our current tId is valid + // + // error: unmapped reads should all be at the end (can stop checking refs) + // + PbiReferenceEntry& unmappedEntry = + rawReferenceEntries_.at(PbiReferenceEntry::UNMAPPED_ID); + if (unmappedEntry.beginRow_ != PbiReferenceEntry::UNSET_ROW) return false; + + // if we've already seen data for this new tId + // (remember we're coming from another tId) + // + // error: refs are out of order (can stop checking refs) + // + PbiReferenceEntry& currentEntry = + rawReferenceEntries_.at(static_cast(tId)); + if (currentEntry.beginRow_ != PbiReferenceEntry::UNSET_ROW) return false; + } + lastRefId_ = tId; + } else if (tId >= 0 && lastPos_ > pos) + return false; // error: positions out of order + + // update row numbers + PbiReferenceEntry& entry = rawReferenceEntries_.at(static_cast(tId)); + if (entry.beginRow_ == PbiReferenceEntry::UNSET_ROW) entry.beginRow_ = rowNumber; + entry.endRow_ = rowNumber + 1; + + // update pos (for sorting check next go-round) + lastPos_ = pos; + return true; + } + + PbiRawReferenceData Result() const + { + // PbiReferenceEntries will be sorted thanks to std::map + // tId will be at end since we're sorting on the uint cast of -1 + PbiRawReferenceData result; + result.entries_.reserve(rawReferenceEntries_.size()); + for (const auto& entry : rawReferenceEntries_) + result.entries_.push_back(entry.second); + return result; + } + + void WriteData(BGZF* bgzf) + { + const auto refData = Result(); + + // num_refs + uint32_t numRefs = refData.entries_.size(); + if (bgzf->is_be) numRefs = ed_swap_4(numRefs); + bgzf_write_safe2(bgzf, &numRefs, 4); + + // reference entries + numRefs = refData.entries_.size(); // need to reset after maybe endian-swapping + for (size_t i = 0; i < numRefs; ++i) { + auto& entry = refData.entries_[i]; + auto tId = entry.tId_; + auto beginRow = entry.beginRow_; + auto endRow = entry.endRow_; + if (bgzf->is_be) { + tId = ed_swap_4(tId); + beginRow = ed_swap_4(beginRow); + endRow = ed_swap_4(endRow); + } + bgzf_write_safe2(bgzf, &tId, 4); + bgzf_write_safe2(bgzf, &beginRow, 4); + bgzf_write_safe2(bgzf, &endRow, 4); + } + } + +private: + int32_t lastRefId_ = -1; + Position lastPos_ = -1; + std::map rawReferenceEntries_; +}; + +// TODO: come back to refseqs, sorting, etc +class PbiBuilder2 +{ + enum class FlushMode + { + FORCE, + NO_FORCE + }; + +public: + PbiBuilder2(const std::string& bamFilename, const std::string& pbiFilename, + const PbiBuilder::CompressionLevel compressionLevel, const size_t numThreads, + const size_t fileBufferSize) + // const size_t numReferenceSequences = 0 + // const bool isCoordinateSorted = false + : bamFilename_{bamFilename}, + pbiFilename_{pbiFilename}, + tempFilename_{pbiFilename + ".build"}, + tempFile_{std::fopen(tempFilename_.c_str(), "w+b")}, + compressionLevel_{compressionLevel}, + numThreads_{numThreads}, + rgIdField_{fileBufferSize}, + qStartField_{fileBufferSize}, + qEndField_{fileBufferSize}, + holeNumField_{fileBufferSize}, + readQualField_{fileBufferSize}, + ctxtField_{fileBufferSize}, + fileOffsetField_{fileBufferSize}, + tIdField_{fileBufferSize}, + tStartField_{fileBufferSize}, + tEndField_{fileBufferSize}, + aStartField_{fileBufferSize}, + aEndField_{fileBufferSize}, + revStrandField_{fileBufferSize}, + nMField_{fileBufferSize}, + nMMField_{fileBufferSize}, + mapQualField_{fileBufferSize}, + bcForwardField_{fileBufferSize}, + bcReverseField_{fileBufferSize}, + bcQualField_{fileBufferSize} + { + if (!tempFile_) + throw std::runtime_error{"IndexedBamWriter: could not open temp file: " + + tempFilename_}; + + // TODO: setup for ref data building + } + + void AddRecord(const BamRecord& b, const int64_t uOffset) + { + // ensure updated data (necessary?) + PacBio::BAM::BamRecordMemory::UpdateRecordTags(b); + b.ResetCachedPositions(); + + // store record data & maybe flush to temp file + AddBasicData(b, uOffset); + AddMappedData(b); + AddBarcodeData(b); + AddReferenceData(b, currentRow_); + FlushBuffers(FlushMode::NO_FORCE); + + ++currentRow_; + } + + void AddBasicData(const BamRecord& b, const int64_t uOffset) + { + // read group ID + const auto rgId = [&b]() -> int32_t { + auto rgIdString = b.ReadGroupBaseId(); + if (rgIdString.empty()) rgIdString = MakeReadGroupId(b.MovieName(), ToString(b.Type())); + return std::stoul(rgIdString, nullptr, 16); + }(); + + // query start/end + const auto isCcsOrTranscript = (IsCcsOrTranscript(b.Type())); + const int32_t qStart = (isCcsOrTranscript ? 0 : b.QueryStart()); + const int32_t qEnd = (isCcsOrTranscript ? b.Impl().SequenceLength() : b.QueryEnd()); + + // add'l data + const int32_t holeNum = (b.HasHoleNumber() ? b.HoleNumber() : 0); + const float readAccuracy = + (b.HasReadAccuracy() ? boost::numeric_cast(b.ReadAccuracy()) : 0.0F); + const uint8_t ctxt = (b.HasLocalContextFlags() ? b.LocalContextFlags() + : LocalContextFlags::NO_LOCAL_CONTEXT); + + // store + rgIdField_.Add(rgId); + qStartField_.Add(qStart); + qEndField_.Add(qEnd); + holeNumField_.Add(holeNum); + ctxtField_.Add(ctxt); + readQualField_.Add(readAccuracy); + fileOffsetField_.Add(uOffset); + } + + void AddMappedData(const BamRecord& b) + { + // alignment position + const auto tId = b.ReferenceId(); + const auto tStart = static_cast(b.ReferenceStart()); + const auto tEnd = static_cast(b.ReferenceEnd()); + const auto aStart = static_cast(b.AlignedStart()); + const auto aEnd = static_cast(b.AlignedEnd()); + const auto isReverseStrand = [&b]() -> uint8_t { + return (b.AlignedStrand() == Strand::REVERSE ? 1 : 0); + }(); + + // alignment quality + const auto matchData = b.NumMatchesAndMismatches(); + const auto nM = static_cast(matchData.first); + const auto nMM = static_cast(matchData.second); + const auto mapQuality = b.MapQuality(); + + if (tId >= 0) hasMappedData_ = true; + + // store + tIdField_.Add(tId); + tStartField_.Add(tStart); + tEndField_.Add(tEnd); + aStartField_.Add(aStart); + aEndField_.Add(aEnd); + revStrandField_.Add(isReverseStrand); + nMField_.Add(nM); + nMMField_.Add(nMM); + mapQualField_.Add(mapQuality); + } + + void AddBarcodeData(const BamRecord& b) + { + // initialize w/ 'missing' value + int16_t bcForward = -1; + int16_t bcReverse = -1; + int8_t bcQuality = -1; + + // check for any barcode data (both required) + if (b.HasBarcodes() && b.HasBarcodeQuality()) { + // fetch data from record + std::tie(bcForward, bcReverse) = b.Barcodes(); + bcQuality = static_cast(b.BarcodeQuality()); + + // double-check & reset to 'missing' value if any less than zero + if (bcForward < 0 && bcReverse < 0 && bcQuality < 0) { + bcForward = -1; + bcReverse = -1; + bcQuality = -1; + } else + hasBarcodeData_ = true; + } + + // store + bcForwardField_.Add(bcForward); + bcReverseField_.Add(bcReverse); + bcQualField_.Add(bcQuality); + } + + void AddReferenceData(const BamRecord& b, const uint32_t currentRow) + { + // only add if coordinate-sorted hint is set + // update with info from refDataBuilder + if (refDataBuilder_) { + const auto sorted = refDataBuilder_->AddRecord(b, currentRow); + if (!sorted) refDataBuilder_.reset(); + } + } + + void Close() + { + if (isClosed_) return; + + FlushBuffers(FlushMode::FORCE); + + OpenPbiFile(); + WritePbiHeader(); + WriteFromTempFile(); + + remove(tempFilename_.c_str()); + isClosed_ = true; + } + + void OpenPbiFile() + { + // open file handle + const auto mode = std::string("wb") + std::to_string(static_cast(compressionLevel_)); + pbiFile_.reset(bgzf_open(pbiFilename_.c_str(), mode.c_str())); + if (pbiFile_ == nullptr) + throw std::runtime_error{"IndexedBamWriter: could not open output PBI file"}; + + // if no explicit thread count given, attempt built-in check + size_t actualNumThreads = numThreads_; + if (actualNumThreads == 0) { + actualNumThreads = std::thread::hardware_concurrency(); + + // if still unknown, default to single-threaded + if (actualNumThreads == 0) actualNumThreads = 1; + } + + // if multithreading requested, enable it + if (actualNumThreads > 1) bgzf_mt(pbiFile_.get(), actualNumThreads, 256); + } + + template + void MaybeFlushBuffer(PbiField2& field, bool force) + { + // replace with lambda, in FlushBuffer(), once PPA can use C++14 ? + if (field.IsFull() || force) { + WriteToTempFile(field); + field.buffer_.clear(); + } + } + + void FlushBuffers(FlushMode mode) + { + const auto force = (mode == FlushMode::FORCE); + + MaybeFlushBuffer(rgIdField_, force); + MaybeFlushBuffer(qStartField_, force); + MaybeFlushBuffer(qEndField_, force); + MaybeFlushBuffer(holeNumField_, force); + MaybeFlushBuffer(readQualField_, force); + MaybeFlushBuffer(ctxtField_, force); + MaybeFlushBuffer(fileOffsetField_, force); + + MaybeFlushBuffer(tIdField_, force); + MaybeFlushBuffer(tStartField_, force); + MaybeFlushBuffer(tEndField_, force); + MaybeFlushBuffer(aStartField_, force); + MaybeFlushBuffer(aEndField_, force); + MaybeFlushBuffer(revStrandField_, force); + MaybeFlushBuffer(nMField_, force); + MaybeFlushBuffer(nMMField_, force); + MaybeFlushBuffer(mapQualField_, force); + + MaybeFlushBuffer(bcForwardField_, force); + MaybeFlushBuffer(bcReverseField_, force); + MaybeFlushBuffer(bcQualField_, force); + } + + template + void LoadFieldBlockFromTempFile(PbiField2& field, const PbiFieldBlock2& block) + { + // seek to block begin + const auto ret = std::fseek(tempFile_.get(), block.pos_, SEEK_SET); + if (ret != 0) + throw std::runtime_error{"IndexedBamWriter: could not seek in temp file: " + + tempFilename_ + ", offset: " + std::to_string(block.pos_)}; + + // read block elements + field.buffer_.assign(block.n_, 0); + const auto numElements = + std::fread(field.buffer_.data(), sizeof(T), block.n_, tempFile_.get()); + + if (numElements != block.n_) + throw std::runtime_error{ + "IndexedBamWriter: could not read expected element count from temp file: " + + tempFilename_}; + } + + template + void WriteField(PbiField2& field) + { + for (const auto& block : field.blocks_) { + LoadFieldBlockFromTempFile(field, block); + WriteBgzfVector2(pbiFile_.get(), field.buffer_); + } + } + + void WriteFromTempFile() + { + // load from temp file, in PBI format order, and write to index + + WriteField(rgIdField_); + WriteField(qStartField_); + WriteField(qEndField_); + WriteField(holeNumField_); + WriteField(readQualField_); + WriteField(ctxtField_); + + WriteVirtualOffsets(); + + if (hasMappedData_) { + WriteField(tIdField_); + WriteField(tStartField_); + WriteField(tEndField_); + WriteField(aStartField_); + WriteField(aEndField_); + WriteField(revStrandField_); + WriteField(nMField_); + WriteField(nMMField_); + WriteField(mapQualField_); + } + + if (refDataBuilder_) WriteReferenceData(); + + if (hasBarcodeData_) { + WriteField(bcForwardField_); + WriteField(bcReverseField_); + WriteField(bcQualField_); + } + } + + template + void WriteToTempFile(PbiField2& field) + { + if (field.buffer_.empty()) return; + + const auto pos = std::ftell(tempFile_.get()); + const auto numElements = + std::fwrite(field.buffer_.data(), sizeof(T), field.buffer_.size(), tempFile_.get()); + field.blocks_.emplace_back(PbiFieldBlock2{pos, numElements}); + } + + void WritePbiHeader() + { + BGZF* bgzf = pbiFile_.get(); + + // 'magic' string + static constexpr const std::array magic{{'P', 'B', 'I', '\1'}}; + bgzf_write_safe2(bgzf, magic.data(), 4); + + PbiFile::Sections sections = PbiFile::BASIC; + if (hasMappedData_) sections |= PbiFile::MAPPED; + if (hasBarcodeData_) sections |= PbiFile::BARCODE; + if (refDataBuilder_) sections |= PbiFile::REFERENCE; + + // version, pbi_flags, & n_reads + auto version = static_cast(PbiFile::CurrentVersion); + uint16_t pbi_flags = sections; + auto numReads = currentRow_; + if (bgzf->is_be) { + version = ed_swap_4(version); + pbi_flags = ed_swap_2(pbi_flags); + numReads = ed_swap_4(numReads); + } + bgzf_write_safe2(bgzf, &version, 4); + bgzf_write_safe2(bgzf, &pbi_flags, 2); + bgzf_write_safe2(bgzf, &numReads, 4); + + // reserved space + char reserved[18]; + memset(reserved, 0, 18); + bgzf_write_safe2(bgzf, reserved, 18); + } + + void WriteReferenceData() { refDataBuilder_->WriteData(pbiFile_.get()); } + + std::vector LoadGzi() + { + // + // Open GZI file & load its contents. About to use for offset transformation. + // + + const std::string gziFn{bamFilename_ + ".gzi"}; + std::unique_ptr gziFile{fopen(gziFn.c_str(), "rb")}; + if (!gziFile) throw std::runtime_error{"IndexedBamWriter: could not open gzi file"}; + + uint64_t numElements; + if (fread(&numElements, sizeof(numElements), 1, gziFile.get()) < 1) + throw std::runtime_error{"IndexedBamWriter: could not read from gziFile"}; + if (ed_is_big()) ed_swap_8(numElements); + + std::vector result; + result.reserve(numElements); + for (uint32_t i = 0; i < numElements; ++i) { + GzIndexEntry entry; + if (fread(&entry.vAddress, sizeof(entry.vAddress), 1, gziFile.get()) < 1) + throw std::runtime_error{"IndexedBamWriter: could not read from gziFile"}; + if (fread(&entry.uAddress, sizeof(entry.uAddress), 1, gziFile.get()) < 1) + throw std::runtime_error{"IndexedBamWriter: could not read from gziFile"}; + if (ed_is_big()) { + ed_swap_8(entry.vAddress); + ed_swap_8(entry.uAddress); + } + result.push_back(std::move(entry)); + } + return result; + } + + void WriteVirtualOffsets() + { + auto index = LoadGzi(); + if (index.empty()) throw std::runtime_error{"IndexedBamWriter: empty GZI file"}; + std::sort(index.begin(), index.end(), + [](const GzIndexEntry& lhs, const GzIndexEntry& rhs) -> bool { + return lhs.uAddress < rhs.uAddress; + }); + + size_t k = 0; + for (const auto& block : fileOffsetField_.blocks_) { + LoadFieldBlockFromTempFile(fileOffsetField_, block); + + // transform offsets from GZI + for (size_t j = 0; j < fileOffsetField_.buffer_.size(); ++j) { + while ((k < index.size() - 1) && (static_cast(index.at(k + 1).uAddress) <= + fileOffsetField_.buffer_[j])) { + ++k; + } + const GzIndexEntry& e = index.at(k); + const int64_t uOffset = fileOffsetField_.buffer_[j] - e.uAddress; + const auto result = ((e.vAddress << 16) | uOffset); + fileOffsetField_.buffer_[j] = result; + } + WriteBgzfVector2(pbiFile_.get(), fileOffsetField_.buffer_); + } + } + +private: + // file info + std::string bamFilename_; + std::string pbiFilename_; + std::string tempFilename_; + std::unique_ptr tempFile_; + std::unique_ptr pbiFile_; + PbiBuilder::CompressionLevel compressionLevel_; + size_t numThreads_; + + // PBI field buffers + PbiField2 rgIdField_; + PbiField2 qStartField_; + PbiField2 qEndField_; + PbiField2 holeNumField_; + PbiField2 readQualField_; + PbiField2 ctxtField_; + PbiField2 fileOffsetField_; + PbiField2 tIdField_; + PbiField2 tStartField_; + PbiField2 tEndField_; + PbiField2 aStartField_; + PbiField2 aEndField_; + PbiField2 revStrandField_; + PbiField2 nMField_; + PbiField2 nMMField_; + PbiField2 mapQualField_; + PbiField2 bcForwardField_; + PbiField2 bcReverseField_; + PbiField2 bcQualField_; + + // reference data + std::unique_ptr refDataBuilder_; + + // tracking data + uint32_t currentRow_ = 0; + bool isClosed_ = false; + bool hasBarcodeData_ = false; + bool hasMappedData_ = false; +}; + +} // namespace internal + +class IndexedBamWriter::IndexedBamWriterPrivate2 //: public internal::FileProducer +{ +public: + IndexedBamWriterPrivate2(const std::string& outputFilename, std::shared_ptr header, + const BamWriter::CompressionLevel bamCompressionLevel, + const size_t numBamThreads, + const PbiBuilder::CompressionLevel pbiCompressionLevel, + const size_t numPbiThreads, const size_t numGziThreads, + const size_t tempFileBufferSize) + : bamFilename_{outputFilename}, header_{header} + { + OpenBam(bamCompressionLevel, numBamThreads); + OpenGzi(numGziThreads); + OpenPbi(pbiCompressionLevel, numPbiThreads, tempFileBufferSize); + + isOpen_ = true; + } + + ~IndexedBamWriterPrivate2() noexcept + { + if (isOpen_) { + try { + Close(); + } catch (...) { + // swallow any exceptions & remain no-throw from dtor + } + } + } + + void Close() + { + // NOTE: keep this order of closing ( BAM -> GZI -> PBI ) + CloseBam(); + CloseGzi(); + ClosePbi(); + + remove(std::string{bamFilename_ + ".gzi"}.c_str()); + isOpen_ = false; + } + + void CloseBam() + { + const auto ret = bgzf_flush(bam_.get()->fp.bgzf); + UNUSED(ret); + bam_.reset(); + } + + void CloseGzi() + { + done_ = true; + gziThread_.join(); + + // TODO: remove GZI file, leaving now for debubging + } + + void ClosePbi() { builder_->Close(); } + + void OpenBam(const BamWriter::CompressionLevel compressionLevel, const size_t numThreads) + { + // + // TODO: Compression level & numThreads are hardcoded here. Ok for + // prototyping but need to be tune-able via API. + // + + if (!header_) + throw std::runtime_error{"IndexedBamWriter: null header provided for output file: " + + bamFilename_}; + + // open output BAM + const auto usingFilename = bamFilename_; + const auto mode = std::string("wb") + std::to_string(static_cast(compressionLevel)); + bam_.reset(sam_open(usingFilename.c_str(), mode.c_str())); + if (!bam_) + throw std::runtime_error{"IndexedBamWriter: could not open file for writing: " + + usingFilename}; + + // maybe set multithreaded writing + size_t actualNumThreads = numThreads; + if (actualNumThreads == 0) { + actualNumThreads = std::thread::hardware_concurrency(); + + // if still unknown, default to single-threaded + if (actualNumThreads == 0) actualNumThreads = 1; + } + if (actualNumThreads > 1) hts_set_threads(bam_.get(), actualNumThreads); + + // write header + auto ret = sam_hdr_write(bam_.get(), header_.get()); + if (ret != 0) + throw std::runtime_error{"IndexedBamWriter: could not write header to file: " + + usingFilename}; + ret = bgzf_flush(bam_.get()->fp.bgzf); + + // store file positions after header + auto headerLength = [](const bam_hdr_t* hdr) -> size_t { + const size_t textHeader = 12 + hdr->l_text; + size_t refHeader = 0; + for (int i = 0; i < hdr->n_targets; ++i) { + char* n = hdr->target_name[i]; + refHeader += (8 + (strlen(n) + 1)); + } + return textHeader + refHeader; + }; + uncompressedFilePos_ = headerLength(header_.get()); + } + + void OpenGzi(size_t numThreads) + { + size_t actualNumThreads = numThreads; + if (actualNumThreads == 0) { + actualNumThreads = std::thread::hardware_concurrency(); + + // if still unknown, default to single-threaded + if (actualNumThreads == 0) actualNumThreads = 1; + } + gziThread_ = std::thread{&IndexedBamWriterPrivate2::RunGziThread, this, actualNumThreads}; + } + + void OpenPbi(const PbiBuilder::CompressionLevel compressionLevel, const size_t numThreads, + const size_t fileBufferSize) + { + builder_ = std::make_unique( + bamFilename_, bamFilename_ + ".pbi", compressionLevel, numThreads, fileBufferSize); + } + + void RunGziThread(size_t numThreads) + { + // + // This thread is the GZI index-enabled reader that trails the writer + // thread(s). It checks for changes in the output BAM's file size & + // reads whatever data is available. When writing is complete, it reads + // anything that might remain & dumps the GZI index contents to disk. + // This index is used downstream to generate records' "virtual offsets". + // + + const auto& bamFilename = bamFilename_; + std::unique_ptr bgzf; + + struct stat st; + int ret = 0; + int64_t lastFileSize = 0; + int64_t numBytesRead = 0; + + auto initBgzf = [&bgzf, &bamFilename, numThreads]() { + bgzf.reset(bgzf_open(bamFilename.c_str(), "rb")); + if (!bgzf) + throw std::runtime_error{ + "IndexedBamWriter: could not open BAM for 'toy train' reading"}; + bgzf_index_build_init(bgzf.get()); + if (numThreads > 1) bgzf_mt(bgzf.get(), numThreads, 256); + }; + + // main thread loop + while (true) { + // Quit if writer thread(s) are finished. + if (done_) break; + + if (stat(bamFilename.c_str(), &st) != 0) { + gziStatus_ = GziStatus::MISC_ERROR; + return; + } + if (st.st_size > lastFileSize) { + lastFileSize = st.st_size; + } else { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + continue; + } + + // Don't read unless we can guarantee we won't catch up to the end of the file. + // Otherwise htslib will think the file has been truncated and throw errors. + // This is a touch tricky because we're reading in multi-thread mode so htslib + // will speculatively start grabbing blocks. So we're going to stay *well* behind + // This needs be made more robust. + // + // Note: It's worth noting that bgzf->block_clength might only be the length of the + // compressed *payload*, meaning if there is any other header/metadata/etc on disk + // in the actual file, our estimation of our trailing distance might be off. If + // this ever starts throwing exceptions we'll have to look more in to this... + while (lastFileSize - numBytesRead > 100 * BGZF_MAX_BLOCK_SIZE) { + // Open BAM reader if not already open. Need to make sure we don't open it + // until we've already established our trailing distance. + if (!bgzf) initBgzf(); + + auto result = bgzf_read_block(bgzf.get()); + if (result != 0) { + gziStatus_ = GziStatus::IO_ERROR; + return; + } + if (bgzf->block_length == 0) { + gziStatus_ = GziStatus::TRAIL_ERROR; + return; + } + numBytesRead += bgzf->block_clength; + } + + // Only update if thigs have appreciably fallen behind + if (lastFileSize - numBytesRead > 1.10 * maxTrailingDistance_) + maxTrailingDistance_ = lastFileSize - numBytesRead; + } + + // Try to open BAM if it wasn't opened in main loop. + if (!bgzf) initBgzf(); + + // Read any remaining data. + while (true) { + auto result = bgzf_read_block(bgzf.get()); + if (result != 0) { + gziStatus_ = GziStatus::IO_ERROR; + return; + } + if (bgzf->block_length == 0) break; + } + + // Dump GZI contents to disk. + const std::string gziFn{bamFilename_ + ".gzi"}; + ret = bgzf_index_dump(bgzf.get(), gziFn.c_str(), nullptr); + if (ret != 0) gziStatus_ = GziStatus::GZI_ERROR; + } + + void Write(const BamRecord& record) + { +// TODO: add API to auto-skip this without special compile flag +#if PBBAM_AUTOVALIDATE + Validator::Validate(record); +#endif + // add record & its to index builder. + // + // NOTE: This is the record's postiion as if it were _uncompressed_. We + // will return with GZI data later to transform it into BAM + // "virtual offset". + // + builder_->AddRecord(record, uncompressedFilePos_); + + const auto rawRecord = BamRecordMemory::GetRawData(record); + + // update bin + // min_shift=14 & n_lvls=5 are BAM "magic numbers" + rawRecord->core.bin = hts_reg2bin(rawRecord->core.pos, bam_endpos(rawRecord.get()), 14, 5); + + // write record to file + const auto ret = sam_write1(bam_.get(), header_.get(), rawRecord.get()); + if (ret <= 0) throw std::runtime_error{"IndexedBamWriter: could not write record to BAM"}; + + // update file position + auto recordLength = [](bam1_t* b) { + auto* c = &b->core; + + static constexpr size_t fixedLength = 36; + const size_t qnameLength = (c->l_qname - c->l_extranul); + + // TODO: long CIGAR handling... sigh... + + size_t remainingLength = 0; + if (c->n_cigar <= 0xffff) + remainingLength = (b->l_data - c->l_qname); + else { + const size_t cigarEnd = ((uint8_t*)bam_get_cigar(b) - b->data) + (c->n_cigar * 4); + remainingLength = 8 + (b->l_data - cigarEnd) + 4 + (4 * c->n_cigar); + } + + return fixedLength + qnameLength + remainingLength; + }; + uncompressedFilePos_ += recordLength(rawRecord.get()); + + // Need to handle any errors from the gzi thread, since it's not set + // up to throw without terminating the program + auto gstatus = gziStatus_.load(); + if (gstatus != GziStatus::GOOD) { + if (gziStatus_.load() == GziStatus::IO_ERROR) + throw std::runtime_error( + "IndexedBamWriter: error in gzi thread reading from BAM file " + bamFilename_); + if (gziStatus_.load() == GziStatus::TRAIL_ERROR) + throw std::runtime_error( + "IndexedBamWriter: gzi reader thread failed to properly trail when reading " + + bamFilename_); + if (gziStatus_.load() == GziStatus::GZI_ERROR) + throw std::runtime_error( + "IndexedBamWriter: could not dump GZI contents for indexing " + bamFilename_); + if (gziStatus_.load() == GziStatus::MISC_ERROR) + throw std::runtime_error("IndexedBamWriter: error computing index file for " + + bamFilename_); + gziStatus_.store(GziStatus::DEAD); + } + } + + size_t MaxReaderLag() const { return maxTrailingDistance_; } + +private: + std::string bamFilename_; + + std::shared_ptr header_; + std::unique_ptr bam_; + std::unique_ptr builder_; + + // used as a type of error return code for the gziThread, so + // that errors are delayed until at least the bam file is + // safely written to disk + enum class GziStatus + { + GOOD, + IO_ERROR, + TRAIL_ERROR, + GZI_ERROR, + MISC_ERROR, + // There was an error, but we've bubbled up the + // information already + DEAD + }; + std::atomic gziStatus_{GziStatus::GOOD}; + std::thread gziThread_; + + bool isOpen_ = false; + + std::atomic done_{false}; + std::atomic maxTrailingDistance_{0}; + + int64_t uncompressedFilePos_ = 0; +}; + +static_assert(!std::is_copy_constructible::value, + "IndexedBamWriter(const IndexedBamWriter&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "IndexedBamWriter& operator=(const IndexedBamWriter&) is not = delete"); + +IndexedBamWriter::IndexedBamWriter(const std::string& outputFilename, const BamHeader& header, + const BamWriter::CompressionLevel bamCompressionLevel, + const size_t numBamThreads, + const PbiBuilder::CompressionLevel pbiCompressionLevel, + const size_t numPbiThreads, const size_t numGziThreads, + const size_t tempFileBufferSize) + : IRecordWriter(), d_{nullptr} +{ + if (tempFileBufferSize % 8 != 0) + throw std::runtime_error{"IndexedBamWriter: invalid buffer size for PBI builder (" + + std::to_string(tempFileBufferSize) + + "). Must be a multiple of 8."}; + +#if PBBAM_AUTOVALIDATE + Validator::Validate(header); +#endif + d_ = std::make_unique( + outputFilename, BamHeaderMemory::MakeRawHeader(header), bamCompressionLevel, numBamThreads, + pbiCompressionLevel, numPbiThreads, numGziThreads, tempFileBufferSize); +} + +IndexedBamWriter::IndexedBamWriter(IndexedBamWriter&&) noexcept = default; + +IndexedBamWriter& IndexedBamWriter::operator=(IndexedBamWriter&&) noexcept = default; + +IndexedBamWriter::~IndexedBamWriter() = default; + +void IndexedBamWriter::TryFlush() {} // ignore + +void IndexedBamWriter::Write(const BamRecord& record) { d_->Write(record); } + +void IndexedBamWriter::Write(const BamRecordImpl& record) { d_->Write(BamRecord{record}); } + +size_t IndexedBamWriter::MaxReaderLag() const { return d_->MaxReaderLag(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/IndexedFastaReader.cpp b/src/IndexedFastaReader.cpp new file mode 100644 index 0000000..0d6b6f0 --- /dev/null +++ b/src/IndexedFastaReader.cpp @@ -0,0 +1,208 @@ +// File Description +/// \file IndexedFastaReader.cpp +/// \brief Implements the IndexedFastaReader class. +// +// Author: David Alexander + +#include "PbbamInternalConfig.h" + +#include "pbbam/IndexedFastaReader.h" + +#include +#include +#include + +#include +#include + +#include "pbbam/BamRecord.h" +#include "pbbam/GenomicInterval.h" +#include "pbbam/Orientation.h" +#include "pbbam/StringUtilities.h" + +#include "MemoryUtils.h" +#include "SequenceUtils.h" + +namespace PacBio { +namespace BAM { + +namespace { + +void ClipAndGapify(std::string& subseq, const Cigar& cigar, bool exciseSoftClips) +{ + size_t seqIndex = 0; + for (const auto& op : cigar) { + const auto type = op.Type(); + const auto opLength = op.Length(); + + // do nothing for hard clips + if (type == CigarOperationType::HARD_CLIP) continue; + + // maybe remove soft clips + if (type == CigarOperationType::SOFT_CLIP) { + if (!exciseSoftClips) { + subseq.reserve(subseq.size() + opLength); + subseq.insert(seqIndex, opLength, '-'); + seqIndex += opLength; + } + } + + // for non-clipping operations + else { + // maybe add gaps/padding + if (type == CigarOperationType::INSERTION) { + subseq.reserve(subseq.size() + opLength); + subseq.insert(seqIndex, opLength, '-'); + } else if (type == CigarOperationType::PADDING) { + subseq.reserve(subseq.size() + opLength); + subseq.insert(seqIndex, opLength, '*'); + } + + // update index + seqIndex += opLength; + } + } +} + +} // namespace + +class IndexedFastaReader::IndexedFastaReaderPrivate +{ +public: + IndexedFastaReaderPrivate(std::string filename) + : fastaFilename_{std::move(filename)}, faiFilename_{fastaFilename_ + ".fai"} + { + handle_.reset(fai_load(fastaFilename_.c_str())); + if (handle_ == nullptr) { + throw std::runtime_error{ + "IndexedFastaReader: could not open index file (*.fai) for FASTA file: " + + fastaFilename_}; + } + } + + std::string fastaFilename_; + std::string faiFilename_; + std::unique_ptr handle_; +}; + +IndexedFastaReader::IndexedFastaReader(std::string filename) + : d_{std::make_unique(std::move(filename))} +{ +} + +IndexedFastaReader::IndexedFastaReader(const IndexedFastaReader& other) + : d_{std::make_unique(other.d_->fastaFilename_)} +{ +} + +IndexedFastaReader::IndexedFastaReader(IndexedFastaReader&&) noexcept = default; + +IndexedFastaReader& IndexedFastaReader::operator=(const IndexedFastaReader& rhs) +{ + if (this != &rhs) *this = IndexedFastaReader{rhs}; + return *this; +} + +IndexedFastaReader& IndexedFastaReader::operator=(IndexedFastaReader&&) noexcept = default; + +IndexedFastaReader::~IndexedFastaReader() = default; + +std::string IndexedFastaReader::Subsequence(const std::string& id, Position begin, + Position end) const +{ + assert(begin <= end); + // htslib is dumb and will not consider empty intervals valid, + // that is, a call to faidx_fetch_seq will *always* return a + // sequence consisting of at least one base. + if (begin == end) return std::string{}; + + int len; + // Derek: *Annoyingly* htslib seems to interpret "end" as inclusive in + // faidx_fetch_seq, whereas it considers it exclusive in the region spec in + // fai_fetch. Can you please verify? + const std::unique_ptr rawSeq{ + faidx_fetch_seq(d_->handle_.get(), id.c_str(), begin, end - 1, &len)}; + if (rawSeq == nullptr) { + std::ostringstream s; + s << "IndexedFastaReader: could not fetch sequence from region: " << id << " [" << begin + << ", " << end << ") in FASTA file: " << d_->fastaFilename_; + throw std::runtime_error{s.str()}; + } + return RemoveAllWhitespace(rawSeq.get()); +} + +std::string IndexedFastaReader::Subsequence(const Data::GenomicInterval& interval) const +{ + return Subsequence(interval.Name(), interval.Start(), interval.Stop()); +} + +std::string IndexedFastaReader::Subsequence(const char* htslibRegion) const +{ + int len = 0; + const std::unique_ptr rawSeq( + fai_fetch(d_->handle_.get(), htslibRegion, &len)); + if (rawSeq == nullptr) { + throw std::runtime_error{"IndexedFastaReader: could not fetch sequence from region: " + + std::string{htslibRegion} + " in FASTA file: " + + d_->fastaFilename_}; + } + return RemoveAllWhitespace(rawSeq.get()); +} + +std::string IndexedFastaReader::ReferenceSubsequence(const BamRecord& bamRecord, + const Orientation orientation, + const bool gapped, + const bool exciseSoftClips) const +{ + std::string subseq = Subsequence(bamRecord.ReferenceName(), bamRecord.ReferenceStart(), + bamRecord.ReferenceEnd()); + + if (bamRecord.Impl().IsMapped() && gapped) + ClipAndGapify(subseq, bamRecord.Impl().CigarData(), exciseSoftClips); + + const auto reverse = + (orientation != Orientation::GENOMIC) && bamRecord.Impl().IsReverseStrand(); + if (reverse) ReverseComplementCaseSens(subseq); + + return subseq; +} + +int IndexedFastaReader::NumSequences() const { return faidx_nseq(d_->handle_.get()); } + +std::vector IndexedFastaReader::Names() const +{ + std::vector names; + names.reserve(NumSequences()); + for (int i = 0; i < NumSequences(); ++i) + names.emplace_back(faidx_iseq(d_->handle_.get(), i)); + return names; +} + +std::string IndexedFastaReader::Name(const size_t idx) const +{ + if (static_cast(idx) >= NumSequences()) { + std::ostringstream s; + s << "IndexedFastaReader: cannot fetch sequence name. Index (" << idx + << ") is larger than the number of sequences: (" << NumSequences() + << ") in FASTA file: " << d_->fastaFilename_; + throw std::runtime_error{s.str()}; + } + return {faidx_iseq(d_->handle_.get(), idx)}; +} + +bool IndexedFastaReader::HasSequence(const std::string& name) const +{ + return (faidx_has_seq(d_->handle_.get(), name.c_str()) != 0); +} + +int IndexedFastaReader::SequenceLength(const std::string& name) const +{ + const auto len = faidx_seq_len(d_->handle_.get(), name.c_str()); + if (len < 0) { + throw std::runtime_error{"IndexedFastaReader: could not determine sequence length of " + + name + " in FASTA file: " + d_->fastaFilename_}; + } + return len; +} +} // namespace BAM +} // namespace PacBio diff --git a/src/IndexedFastqBgzfReader.cpp b/src/IndexedFastqBgzfReader.cpp new file mode 100644 index 0000000..f363d17 --- /dev/null +++ b/src/IndexedFastqBgzfReader.cpp @@ -0,0 +1,141 @@ +// File Description +/// \file BgzFastqLoader.cpp +/// \brief Implements the IndexedFastqBgzfReaderr class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "IndexedFastqBgzfReader.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { + +IndexedFastqBgzfReader::IndexedFastqBgzfReader(std::string filename) + : IndexedFastqReaderImpl{std::move(filename)} + , file_{bgzf_open(fastqFilename_.c_str(), "r")} + , seq_{kseq_init(file_.get())} +{ + // check BGZF file handle + if (file_ == nullptr) { + std::ostringstream msg; + msg << "IndexedFastqBgzfReader: could not open file for reading\n" + << " FASTQ file: " << fastqFilename_ << '\n'; + throw std::runtime_error{msg.str()}; + } + + // check kseq sequence handle + assert(seq_ != nullptr); + + // load BGZF index data (*.gzi) + const auto result = bgzf_index_load(file_.get(), fastqFilename_.c_str(), ".gzi"); + if (result != 0) { + std::ostringstream msg; + msg << "IndexedFastqBgzfReader: could not load bgzf index data\n" + << " FASTQ file: " << fastqFilename_ << '\n' + << " index file: " << fastqFilename_ << ".gzi\n"; + throw std::runtime_error{msg.str()}; + } +} + +int IndexedFastqBgzfReader::FetchRecord() +{ + // NOTE: kseq_read assumes it is at the beginning of "next" sequence's name. + // However, here the file handle already points to the first base after + // seeking using FAI. So this is kseq_read without the name/comment scan. + + int c; + kseq_t* seq = seq_.get(); + kstream_t* ks = seq->f; + seq_->comment.l = seq_->seq.l = seq_->qual.l = 0; /* reset all members */ + if (seq_->seq.s == 0) { /* we can do this in the loop below, but that is slower */ + seq_->seq.m = 256; + seq_->seq.s = (char*)malloc(seq_->seq.m); + } + while ((c = ks_getc(ks)) != -1 && c != '>' && c != '+' && c != '@') { + if (c == '\n') continue; /* skip empty lines */ + seq_->seq.s[seq_->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ + ks_getuntil2(ks, KS_SEP_LINE, &seq_->seq, 0, 1); /* read the rest of the line */ + } + + if (c == '>' || c == '@') seq_->last_char = c; /* the first header char has been read */ + if (seq_->seq.l + 1 >= + seq_->seq.m) { /* seq_->seq.s[seq_->seq.l] below may be out of boundary */ + seq_->seq.m = seq_->seq.l + 2; + kroundup32(seq_->seq.m); /* rounded to the next closest 2^k */ + seq_->seq.s = (char*)realloc(seq_->seq.s, seq_->seq.m); + } + seq_->seq.s[seq_->seq.l] = 0; /* null terminated string */ + if (c != '+') return seq_->seq.l; /* FASTA */ + if (seq_->qual.m < seq_->seq.m) { /* allocate memory for qual in case insufficient */ + seq_->qual.m = seq_->seq.m; + seq_->qual.s = (char*)realloc(seq_->qual.s, seq_->qual.m); + } + + while ((c = ks_getc(ks)) != -1 && c != '\n') + ; /* skip the rest of '+' line */ + if (c == -1) return -2; /* error: no quality string */ + while (ks_getuntil2(ks, KS_SEP_LINE, &seq_->qual, 0, 1) >= 0 && seq_->qual.l < seq_->seq.l) + ; + seq_->last_char = 0; /* we have not come to the next header line */ + + if (seq_->seq.l != seq_->qual.l) return -2; /* error: qual string is of a different length */ + return seq_->seq.l; +} + +std::pair IndexedFastqBgzfReader::Subsequence(const std::string& id, + Position start, + Position end) +{ + // check requested region is valid + const auto& entry = index_.Entry(id); + const int64_t available = static_cast(entry.Length) - start; + const int64_t requested = end - start; + const int64_t length = std::min(available, requested); + if ((start < 0) || (end < 0) || (length < 0)) { + std::ostringstream msg; + msg << "IndexedFastqBgzfReader: invalid subsequence region requested from\n" + << " FASTQ file: " << fastqFilename_ << '\n' + << " requested region: " << id << ':' << start << '-' << end << '\n' + << " sequence length: " << entry.Length << '\n'; + throw std::runtime_error{msg.str()}; + } + + // quick out if nothing needed + if (length == 0) return {}; + + // seek to sequence 'id' & reset kseq handle + auto result = bgzf_useek(file_.get(), entry.SeqOffset, SEEK_SET); + if (result != 0) { + std::ostringstream msg; + msg << "IndexedFastqBgzfReader: could not seek to requested region\n" + << " FASTQ file: " << fastqFilename_ << '\n' + << " requested region: " << id << ':' << start << '-' << end << '\n'; + throw std::runtime_error{msg.str()}; + } + ks_rewind(seq_->f); + + // read (entire) sequence + result = FetchRecord(); + if (result < 0) { + std::ostringstream msg; + msg << "IndexedFastqBgzfReader: error reading from\n" + << " FASTQ file: " << fastqFilename_ << '\n' + << " requested region: " << id << ':' << start << '-' << end << '\n' + << " reason: likely truncated quality string\n"; + throw std::runtime_error{msg.str()}; + } + + // trim to region bounds and return + const std::string seq{seq_->seq.s, seq_->seq.l}; + const std::string quals{seq_->qual.s, seq_->qual.l}; + return std::make_pair(seq.substr(start, length), + QualityValues::FromFastq(quals.substr(start, length))); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/IndexedFastqBgzfReader.h b/src/IndexedFastqBgzfReader.h new file mode 100644 index 0000000..3ec294e --- /dev/null +++ b/src/IndexedFastqBgzfReader.h @@ -0,0 +1,52 @@ +// File Description +/// \file IndexedFastqBgzfReader.h +/// \brief Defines the IndexedFastqBgzfReader class. +// +// Author: Derek Barnett + +#ifndef INDEXEDFASTQBGZFREADER_H +#define INDEXEDFASTQBGZFREADER_H + +#include "pbbam/Config.h" + +#include "IndexedFastqReaderImpl.h" + +#include + +#include + +#include "MemoryUtils.h" + +namespace PacBio { +namespace BAM { + +class IndexedFastqBgzfReader final : public IndexedFastqReaderImpl +{ +public: + IndexedFastqBgzfReader(std::string filename); + + std::pair Subsequence(const std::string& id, Position start, + Position end) final; + +private: + int FetchRecord(); + + // specialize kseq_t for BGZF handle + KSEQ_INIT(BGZF*, bgzf_read); + struct KSeqDeleter + { + void operator()(kseq_t* seq) const + { + if (seq) kseq_destroy(seq); + seq = nullptr; + } + }; + + std::unique_ptr file_; + std::unique_ptr seq_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // INDEXEDFASTQBGZFREADER_H \ No newline at end of file diff --git a/src/IndexedFastqReader.cpp b/src/IndexedFastqReader.cpp new file mode 100644 index 0000000..d59cdad --- /dev/null +++ b/src/IndexedFastqReader.cpp @@ -0,0 +1,198 @@ +// File Description +/// \file IndexedFastqReader.cpp +/// \brief Implements the IndexedFastqReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/IndexedFastqReader.h" + +#include +#include +#include + +#include "pbbam/BamRecord.h" +#include "pbbam/FaiIndex.h" +#include "pbbam/FormatUtils.h" +#include "pbbam/GenomicInterval.h" + +#include "IndexedFastqBgzfReader.h" +#include "IndexedFastqReaderImpl.h" +#include "IndexedFastqTextReader.h" +#include "SequenceUtils.h" + +namespace PacBio { +namespace BAM { + +namespace { + +void ClipAndGapify(std::pair& seqQual, const Cigar& cigar, + bool exciseSoftClips) +{ + auto& subseq = seqQual.first; + auto subQual = seqQual.second.Fastq(); + + const char nullQual = QualityValue{0}.Fastq(); + + size_t seqIndex = 0; + for (const auto& op : cigar) { + const auto type = op.Type(); + const auto opLength = op.Length(); + + // do nothing for hard clips + if (type == CigarOperationType::HARD_CLIP) continue; + + // maybe remove soft clips + if (type == CigarOperationType::SOFT_CLIP) { + if (!exciseSoftClips) { + subseq.reserve(subseq.size() + opLength); + subseq.insert(seqIndex, opLength, '-'); + subQual.reserve(subQual.size() + opLength); + subQual.insert(seqIndex, opLength, nullQual); + seqIndex += opLength; + } + } + + // for non-clipping operations + else { + // maybe add gaps/padding + if (type == CigarOperationType::INSERTION) { + subseq.reserve(subseq.size() + opLength); + subseq.insert(seqIndex, opLength, '-'); + subQual.reserve(subseq.size() + opLength); + subQual.insert(seqIndex, opLength, nullQual); + } else if (type == CigarOperationType::PADDING) { + subseq.reserve(subseq.size() + opLength); + subseq.insert(seqIndex, opLength, '*'); + subQual.reserve(subseq.size() + opLength); + subQual.insert(seqIndex, opLength, nullQual); + } + + // update index + seqIndex += opLength; + } + } + + seqQual.second = QualityValues::FromFastq(subQual); +} + +std::unique_ptr MakeReaderImpl(std::string filename) +{ + // validate extension + if (!FormatUtils::IsFastqFilename(filename)) { + throw std::runtime_error{"IndexedFastqReader: filename '" + filename + + "' is not recognized as a FASTQ file."}; + } + + // determine subsequence "loader" from compression type: plain-text, bgzf, or unsupported + const auto compressionType = FormatUtils::CompressionType(filename); + switch (compressionType) { + + case HtslibCompression::NONE: + return std::make_unique(std::move(filename)); + case HtslibCompression::BGZIP: + return std::make_unique(std::move(filename)); + + case HtslibCompression::GZIP: { + std::ostringstream msg; + msg << "IndexedFastqReader: random-access is not supported for plain gzipped " + "file " + << filename << "\n\n" + << "Compressed files must be bgzipped, with accompanying *.gzi " + "index.\n\n" + << "To keep the original gzipped file unchanged:\n" + << " $ gunzip -c " << filename << " > \n" + << "or discard the gzipped file:\n" + << " $ gunzip " << filename << '\n' + << '\n' + << "Re-compress & create *.gzi index:\n" + << " $ bgzip --index \n\n"; + throw std::runtime_error{msg.str()}; + } + default: + assert(false); // should never get here, the way htslib currently determines type + throw std::runtime_error{ + "IndexedFastqReader: could not determine compression type for file: " + filename}; + } +} + +} // namespace + +IndexedFastqReader::IndexedFastqReader(std::string filename) + : d_{MakeReaderImpl(std::move(filename))} +{ +} + +IndexedFastqReader::IndexedFastqReader(const IndexedFastqReader& other) + : d_{MakeReaderImpl(other.d_->faiFilename_)} +{ +} + +IndexedFastqReader::IndexedFastqReader(IndexedFastqReader&&) noexcept = default; + +IndexedFastqReader& IndexedFastqReader::operator=(const IndexedFastqReader& rhs) +{ + if (this != &rhs) *this = IndexedFastqReader{rhs}; + return *this; +} + +IndexedFastqReader& IndexedFastqReader::operator=(IndexedFastqReader&&) noexcept = default; + +IndexedFastqReader::~IndexedFastqReader() = default; + +bool IndexedFastqReader::HasSequence(const std::string& name) const +{ + return d_->index_.HasEntry(name); +} + +std::vector IndexedFastqReader::Names() const { return d_->index_.Names(); } + +std::string IndexedFastqReader::Name(const size_t idx) const { return d_->index_.Names().at(idx); } + +int IndexedFastqReader::NumSequences() const { return d_->index_.Names().size(); } + +std::pair IndexedFastqReader::ReferenceSubsequence( + const BamRecord& bamRecord, const Orientation orientation, const bool gapped, + const bool exciseSoftClips) +{ + // fetch raw data for record's region + auto seqQual = Subsequence(bamRecord.ReferenceName(), bamRecord.ReferenceStart(), + bamRecord.ReferenceEnd()); + + // maybe clip/gapify + if (bamRecord.Impl().IsMapped() && gapped) { + ClipAndGapify(seqQual, bamRecord.Impl().CigarData(), exciseSoftClips); + } + + // maybe reverse + const auto reverse = + (orientation != Orientation::GENOMIC) && bamRecord.Impl().IsReverseStrand(); + if (reverse) { + ReverseComplementCaseSens(seqQual.first); + Reverse(seqQual.second); + } + + return seqQual; +} + +int IndexedFastqReader::SequenceLength(const std::string& name) const +{ + const auto& entry = d_->index_.Entry(name); + return static_cast(entry.Length); +} + +std::pair IndexedFastqReader::Subsequence(const std::string& id, + Position start, Position end) +{ + return d_->Subsequence(id, start, end); +} + +std::pair IndexedFastqReader::Subsequence( + const GenomicInterval& interval) +{ + return Subsequence(interval.Name(), interval.Start(), interval.Stop()); +} + +} // namespace BAM +} // namespace PacBio \ No newline at end of file diff --git a/src/IndexedFastqReaderImpl.cpp b/src/IndexedFastqReaderImpl.cpp new file mode 100644 index 0000000..3b4a2ef --- /dev/null +++ b/src/IndexedFastqReaderImpl.cpp @@ -0,0 +1,24 @@ +// File Description +/// \file IndexedFastqReaderImpl.cpp +/// \brief Implements the IndexedFastqReaderImpl class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "IndexedFastqReaderImpl.h" + +namespace PacBio { +namespace BAM { + +IndexedFastqReaderImpl::IndexedFastqReaderImpl(std::string filename) + : fastqFilename_{std::move(filename)} + , faiFilename_{fastqFilename_ + ".fai"} + , index_{faiFilename_} +{ +} + +IndexedFastqReaderImpl::~IndexedFastqReaderImpl() = default; + +} // namespace BAM +} // namespace PacBio diff --git a/src/IndexedFastqReaderImpl.h b/src/IndexedFastqReaderImpl.h new file mode 100644 index 0000000..da1e616 --- /dev/null +++ b/src/IndexedFastqReaderImpl.h @@ -0,0 +1,43 @@ +// File Description +/// \file IndexedFastqReaderImpl.h +/// \brief Defines the IndexedFastqReaderImpl class. +// +// Author: Derek Barnett + +#ifndef INDEXEDFASTQREADERIMPL_H +#define INDEXEDFASTQREADERIMPL_H + +#include "pbbam/Config.h" + +#include +#include + +#include +#include + +#include "pbbam/FaiIndex.h" + +namespace PacBio { +namespace BAM { + +class IndexedFastqReaderImpl +{ +public: + virtual ~IndexedFastqReaderImpl(); + + virtual std::pair Subsequence(const std::string& id, + Data::Position start, + Data::Position end) = 0; + + std::string fastqFilename_; + std::string faiFilename_; + FaiIndex index_; + +protected: + IndexedFastqReaderImpl(std::string filename); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // INDEXEDFASTQREADERIMPL_H \ No newline at end of file diff --git a/src/IndexedFastqTextReader.cpp b/src/IndexedFastqTextReader.cpp new file mode 100644 index 0000000..4b4e23f --- /dev/null +++ b/src/IndexedFastqTextReader.cpp @@ -0,0 +1,142 @@ +// File Description +/// \file IndexedFastqTextReader.cpp +/// \brief Implements the IndexedFastqTextReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "IndexedFastqTextReader.h" + +#include +#include +#include + +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +IndexedFastqTextReader::IndexedFastqTextReader(std::string filename) + : IndexedFastqReaderImpl{std::move(filename)} + , file_{fopen(fastqFilename_.c_str(), "r")} + , seq_{kseq_init(file_.get())} +{ + // check file handle + if (file_ == nullptr) { + std::ostringstream msg; + msg << "IndexedFastqTextReader: could not open file for reading\n" + << " FASTQ file: " << fastqFilename_ << '\n'; + throw std::runtime_error{msg.str()}; + } + + // check kseq sequence handle + assert(seq_ != nullptr); +} + +int IndexedFastqTextReader::FetchRecord() +{ + // NOTE: kseq_read assumes it is at the beginning of "next" sequence's name. + // However, here the file handle already points to the first base after + // seeking using FAI. So this is kseq_read without the name/comment scan. + + int c; + kseq_t* seq = seq_.get(); + kstream_t* ks = seq->f; + seq_->comment.l = seq_->seq.l = seq_->qual.l = 0; /* reset all members */ + if (seq_->seq.s == 0) { /* we can do this in the loop below, but that is slower */ + seq_->seq.m = 256; + seq_->seq.s = (char*)malloc(seq_->seq.m); + } + while ((c = ks_getc(ks)) != -1 && c != '>' && c != '+' && c != '@') { + if (c == '\n') continue; /* skip empty lines */ + seq_->seq.s[seq_->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ + ks_getuntil2(ks, KS_SEP_LINE, &seq_->seq, 0, 1); /* read the rest of the line */ + } + + if (c == '>' || c == '@') seq_->last_char = c; /* the first header char has been read */ + if (seq_->seq.l + 1 >= + seq_->seq.m) { /* seq_->seq.s[seq_->seq.l] below may be out of boundary */ + seq_->seq.m = seq_->seq.l + 2; + kroundup32(seq_->seq.m); /* rounded to the next closest 2^k */ + seq_->seq.s = (char*)realloc(seq_->seq.s, seq_->seq.m); + } + seq_->seq.s[seq_->seq.l] = 0; /* null terminated string */ + + if (c != '+') return seq_->seq.l; /* FASTA */ + if (seq_->qual.m < seq_->seq.m) { /* allocate memory for qual in case insufficient */ + seq_->qual.m = seq_->seq.m; + seq_->qual.s = (char*)realloc(seq_->qual.s, seq_->qual.m); + } + + while ((c = ks_getc(ks)) != -1 && c != '\n') + ; /* skip the rest of '+' line */ + if (c == -1) return -2; /* error: no quality string */ + while (ks_getuntil2(ks, KS_SEP_LINE, &seq_->qual, 0, 1) >= 0 && seq_->qual.l < seq_->seq.l) + ; + + seq_->last_char = 0; /* we have not come to the next header line */ + + if (seq_->seq.l != seq_->qual.l) return -2; /* error: qual string is of a different length */ + return seq_->seq.l; +} + +int IndexedFastqTextReader::ReadFromFile(FILE* fp, void* data, size_t length) +{ + return static_cast(std::fread(data, sizeof(uint8_t), length, fp)); +} + +std::pair IndexedFastqTextReader::Subsequence( + const std::string& id, Data::Position start, Data::Position end) +{ + // check requested region is valid + const auto& entry = index_.Entry(id); + const int64_t available = static_cast(entry.Length) - start; + const int64_t requested = end - start; + const int64_t length = std::min(available, requested); + if ((start < 0) || (end < 0) || (length < 0)) { + std::ostringstream msg; + msg << "IndexedFastqTextReader: invalid subsequence region requested from\n" + << " FASTQ file: " << fastqFilename_ << '\n' + << " requested region: " << id << ':' << start << '-' << end << '\n' + << " sequence length: " << entry.Length << '\n'; + throw std::runtime_error{msg.str()}; + } + + // quick out if nothing needed + if (length == 0) return {}; + + // seek to sequence 'id' & reset kseq handle + auto result = fseek(file_.get(), entry.SeqOffset, SEEK_SET); + if (result != 0) { + std::ostringstream msg; + msg << "IndexedFastqTextReader: could not seek to requested region\n" + << " FASTQ file: " << fastqFilename_ << '\n' + << " requested region: " << id << ':' << start << '-' << end << '\n'; + throw std::runtime_error{msg.str()}; + } + ks_rewind(seq_->f); + + // read (entire) sequence + result = FetchRecord(); + if (result < 0) { + std::ostringstream msg; + msg << "IndexedFastqTextReader: error reading from\n" + << " FASTQ file: " << fastqFilename_ << '\n' + << " requested region: " << id << ':' << start << '-' << end << '\n' + << " reason: likely truncated quality string\n"; + throw std::runtime_error{msg.str()}; + } + + // trim to region bounds and return + const std::string seq{seq_->seq.s, seq_->seq.l}; + const std::string quals{seq_->qual.s, seq_->qual.l}; + return std::make_pair(seq.substr(start, length), + Data::QualityValues::FromFastq(quals.substr(start, length))); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/IndexedFastqTextReader.h b/src/IndexedFastqTextReader.h new file mode 100644 index 0000000..b77992e --- /dev/null +++ b/src/IndexedFastqTextReader.h @@ -0,0 +1,59 @@ +// File Description +/// \file IndexedFastqTextReader.h +/// \brief Defines the IndexedFastqTextReader class. +// +// Author: Derek Barnett + +#ifndef INDEXEDFASTQTEXTREADER_H +#define INDEXEDFASTQTEXTREADER_H + +#include "pbbam/Config.h" + +#include "IndexedFastqReaderImpl.h" + +#include + +#include + +#include +#include + +namespace PacBio { +namespace BAM { + +class IndexedFastqTextReader final : public IndexedFastqReaderImpl +{ +public: + IndexedFastqTextReader(std::string filename); + + std::pair Subsequence(const std::string& id, + Data::Position start, + Data::Position end) final; + +private: + int FetchRecord(); + + // kseq needs a '__read' function with this signature, so fread does not work + // in this case. gzread/bgzf_read match but we want better seek performance + // than gzstream and are specifically not using indexed BGZF + static int ReadFromFile(FILE* fp, void* data, size_t length); + + // specialize kseq_t for FILE handle + KSEQ_INIT(FILE*, ReadFromFile) + struct KSeqDeleter + { + void operator()(kseq_t* seq) const + { + if (seq) kseq_destroy(seq); + seq = nullptr; + } + }; + + std::unique_ptr file_; + std::unique_ptr seq_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // INDEXEDFASTQTEXTREADER_H \ No newline at end of file diff --git a/src/KSeqReader.cpp b/src/KSeqReader.cpp new file mode 100644 index 0000000..4caf6ed --- /dev/null +++ b/src/KSeqReader.cpp @@ -0,0 +1,54 @@ +// File Description +/// \file KSeqReader.cpp +/// \brief Implements the KSeqReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "KSeqReader.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { + +KSeqReader::KSeqReader(const std::string& fn) + : fp_{gzopen(fn.c_str(), "r")}, seq_{kseq_init(fp_.get())} +{ + // check file handle + if (fp_ == nullptr) { + std::ostringstream msg; + msg << "KSeqReader: could not open file for reading\n" + << " file: " << fn << '\n'; + throw std::runtime_error{msg.str()}; + } + + // check kseq sequence handle + assert(seq_ != nullptr); +} + +KSeqReader::KSeqReader(KSeqReader&&) noexcept = default; + +KSeqReader& KSeqReader::operator=(KSeqReader&&) noexcept = default; + +KSeqReader::~KSeqReader() = default; + +std::string KSeqReader::Bases() const { return std::string{seq_->seq.s, seq_->seq.l}; } + +std::string KSeqReader::Name() const { return std::string{seq_->name.s, seq_->name.l}; } + +std::string KSeqReader::Qualities() const { return std::string{seq_->qual.s, seq_->qual.l}; } + +bool KSeqReader::ReadNext() +{ + const auto result = kseq_read(seq_.get()); + if (result == -1) // EOF + return false; + return true; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/KSeqReader.h b/src/KSeqReader.h new file mode 100644 index 0000000..9594ae6 --- /dev/null +++ b/src/KSeqReader.h @@ -0,0 +1,59 @@ +// File Description +/// \file KSeqReader.h +/// \brief Defines the KSeqReader class. +// +// Author: Derek Barnett + +#ifndef KSEQREADER_H +#define KSEQREADER_H + +#include "pbbam/Config.h" + +#include +#include + +#include +#include + +#include "MemoryUtils.h" + +namespace PacBio { +namespace BAM { + +class KSeqReader +{ +public: + explicit KSeqReader(const std::string& fn); + + KSeqReader(const KSeqReader&) = delete; + KSeqReader(KSeqReader&&) noexcept; + KSeqReader& operator=(const KSeqReader&) = delete; + KSeqReader& operator=(KSeqReader&&) noexcept; + virtual ~KSeqReader(); + + std::string Name() const; + std::string Bases() const; + std::string Qualities() const; + + bool ReadNext(); + +private: + // specialize kseq for gzstream (handles all of our types) + KSEQ_INIT(gzFile, gzread) + struct KSeqDeleter + { + void operator()(kseq_t* seq) const + { + if (seq) kseq_destroy(seq); + seq = nullptr; + } + }; + + std::unique_ptr fp_; + std::unique_ptr seq_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // KSEQREADER_H diff --git a/src/MD5.cpp b/src/MD5.cpp new file mode 100644 index 0000000..6be55a2 --- /dev/null +++ b/src/MD5.cpp @@ -0,0 +1,54 @@ +// File Description +/// \file MD5.cpp +/// \brief Implements basic MD5 hash utilities +// +// Author: Brett Bowman + +#include "PbbamInternalConfig.h" + +#include "pbbam/MD5.h" + +#include + +#include + +namespace PacBio { +namespace BAM { + +class Md5ContextHelper +{ +public: + Md5ContextHelper() : data_(hts_md5_init()) + { + if (data_ == nullptr) throw std::runtime_error{"MD5: could not initialize context"}; + } + + ~Md5ContextHelper() { hts_md5_destroy(data_); } + + std::string Encoded(const std::string& str) + { + hts_md5_update(data_, reinterpret_cast(const_cast(str.c_str())), str.size()); + + unsigned char digest[16]; + hts_md5_final(digest, data_); + + char hexdigest[33]; // leave space for null-term + hts_md5_hex(hexdigest, digest); + + return std::string{hexdigest, 32}; + } + +private: + hts_md5_context* data_; +}; + +/// \brief MD5 hash of a string as a 32-digit hexadecimal string +/// +std::string MD5Hash(const std::string& str) +{ + Md5ContextHelper md5; + return md5.Encoded(str); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/MemoryUtils.cpp b/src/MemoryUtils.cpp new file mode 100644 index 0000000..9be40a8 --- /dev/null +++ b/src/MemoryUtils.cpp @@ -0,0 +1,40 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "MemoryUtils.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { + +BamHeader BamHeaderMemory::FromRawData(bam_hdr_t* hdr) +{ + // null input - error + if (hdr == nullptr) throw std::runtime_error{"MemoryUtils: null BAM header"}; + + // empty text input - ok + if (hdr->text == nullptr || hdr->l_text == 0) return BamHeader(); + + // parse normal SAM text input + return BamHeader(std::string(hdr->text, hdr->l_text)); +} + +std::shared_ptr BamHeaderMemory::MakeRawHeader(const BamHeader& header) +{ + const std::string text = header.ToSam(); + std::shared_ptr rawData(sam_hdr_parse(text.size(), text.c_str()), + HtslibHeaderDeleter()); + rawData->ignore_sam_err = 0; + rawData->cigar_tab = nullptr; + rawData->l_text = text.size(); + rawData->text = static_cast(calloc(rawData->l_text + 1, 1)); + memcpy(rawData->text, text.c_str(), rawData->l_text); + return rawData; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/MemoryUtils.h b/src/MemoryUtils.h new file mode 100644 index 0000000..1679f76 --- /dev/null +++ b/src/MemoryUtils.h @@ -0,0 +1,151 @@ +// Author: Derek Barnett + +#ifndef MEMORYUTILS_H +#define MEMORYUTILS_H + +#include "pbbam/Config.h" + +#include +#include + +#include +#include +#include +#include + +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/BamRecordImpl.h" + +namespace PacBio { +namespace BAM { + +class BamHeader; + +// intended for use with std::shared_ptr, std::unique_ptr, etc + +struct GzFileDeleter +{ + void operator()(gzFile fp) const + { + if (fp) gzclose(fp); + fp = nullptr; + } +}; + +struct HtslibBgzfDeleter +{ + void operator()(BGZF* bgzf) const + { + if (bgzf) bgzf_close(bgzf); + bgzf = nullptr; + } +}; + +struct HtslibFastaIndexDeleter +{ + void operator()(faidx_t* fai) const + { + if (fai) fai_destroy(fai); + fai = nullptr; + } +}; + +struct HtslibFileDeleter +{ + void operator()(samFile* file) const + { + if (file) sam_close(file); + file = nullptr; + } +}; + +struct HtslibHeaderDeleter +{ + void operator()(bam_hdr_t* hdr) const + { + if (hdr) bam_hdr_destroy(hdr); + hdr = nullptr; + } +}; + +struct HtslibIndexDeleter +{ + void operator()(hts_idx_t* index) const + { + if (index) hts_idx_destroy(index); + index = nullptr; + } +}; + +struct HtslibIteratorDeleter +{ + void operator()(hts_itr_t* iter) const + { + if (iter) hts_itr_destroy(iter); + iter = nullptr; + } +}; + +struct HtslibRecordDeleter +{ + void operator()(bam1_t* b) const + { + if (b) bam_destroy1(b); + b = nullptr; + } +}; + +class BamHeaderMemory +{ +public: + static BamHeader FromRawData(bam_hdr_t* header); + static std::shared_ptr MakeRawHeader(const BamHeader& header); +}; + +class BamRecordMemory +{ +public: + static const BamRecordImpl& GetImpl(const BamRecord& r); + static const BamRecordImpl& GetImpl(const BamRecord* r); + static std::shared_ptr GetRawData(const BamRecord& r); + static std::shared_ptr GetRawData(const BamRecord* r); + static std::shared_ptr GetRawData(const BamRecordImpl& impl); + static std::shared_ptr GetRawData(const BamRecordImpl* impl); + + static void UpdateRecordTags(const BamRecord& r); + static void UpdateRecordTags(const BamRecordImpl& r); +}; + +inline const BamRecordImpl& BamRecordMemory::GetImpl(const BamRecord& r) { return r.impl_; } + +inline const BamRecordImpl& BamRecordMemory::GetImpl(const BamRecord* r) { return r->impl_; } + +inline std::shared_ptr BamRecordMemory::GetRawData(const BamRecord& r) +{ + return GetRawData(r.impl_); +} + +inline std::shared_ptr BamRecordMemory::GetRawData(const BamRecord* r) +{ + return GetRawData(r->impl_); +} + +inline std::shared_ptr BamRecordMemory::GetRawData(const BamRecordImpl& impl) +{ + return impl.d_; +} + +inline std::shared_ptr BamRecordMemory::GetRawData(const BamRecordImpl* impl) +{ + return impl->d_; +} + +inline void BamRecordMemory::UpdateRecordTags(const BamRecord& r) { UpdateRecordTags(r.impl_); } + +inline void BamRecordMemory::UpdateRecordTags(const BamRecordImpl& r) { r.UpdateTagMap(); } + +} // namespace BAM +} // namespace PacBio + +#endif // MEMORYUTILS_H diff --git a/src/PbbamInternalConfig.h b/src/PbbamInternalConfig.h new file mode 100644 index 0000000..340b97d --- /dev/null +++ b/src/PbbamInternalConfig.h @@ -0,0 +1,18 @@ +// File Description +/// \file PbbamInternalConfig.h +/// \brief Defines internal macros for symbol visibility +// +// Author: Derek Barnett + +#ifndef PBBAMINTERNALCONFIG_H +#define PBBAMINTERNALCONFIG_H + +#if defined(WIN32) +#define PBBAM_EXPORT __declspec(dllexport) +#else +#define PBBAM_EXPORT __attribute__((visibility("default"))) +#endif + +#include "pbbam/Config.h" + +#endif // PBBAMINTERNALCONFIG_H diff --git a/src/PbiBuilder.cpp b/src/PbiBuilder.cpp new file mode 100644 index 0000000..3f710b4 --- /dev/null +++ b/src/PbiBuilder.cpp @@ -0,0 +1,662 @@ +// File Description +/// \file PbiBuilder.cpp +/// \brief Implements the PbiBuilder class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/PbiBuilder.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include "MemoryUtils.h" +#include "pbbam/BamRecord.h" +#include "pbbam/BamRecordImpl.h" +#include "pbbam/PbiRawData.h" +#include "pbbam/RecordType.h" + +namespace PacBio { +namespace BAM { +namespace internal { + +template +inline void SwapEndianness(std::vector& data) +{ + const size_t elementSize = sizeof(T); + const size_t numReads = data.size(); + switch (elementSize) { + case 1: + break; // no swapping necessary + case 2: + for (size_t i = 0; i < numReads; ++i) + ed_swap_2p(&data[i]); + break; + case 4: + for (size_t i = 0; i < numReads; ++i) + ed_swap_4p(&data[i]); + break; + case 8: + for (size_t i = 0; i < numReads; ++i) + ed_swap_8p(&data[i]); + break; + default: + throw std::runtime_error{"PbiBuilder: unsupported element size (" + + std::to_string(elementSize) + ")"}; + } +} + +void bgzf_write_safe(BGZF* fp, const void* data, size_t length) +{ + const auto ret = bgzf_write(fp, data, length); + if (ret < 0L) + throw std::runtime_error{ + "PbiBuilder: non-zero returned from bgzf_write(). Out of disk space?"}; +} + +template +inline void WriteBgzfVector(BGZF* fp, std::vector& data) +{ + assert(fp); + if (fp->is_be) SwapEndianness(data); + bgzf_write_safe(fp, &data[0], data.size() * sizeof(T)); +} + +struct PbiFieldBlock +{ + int64_t pos_; // file position of block start + size_t n_; // number of entries in block +}; + +template +class PbiField +{ + constexpr static const size_t ElementSize = sizeof(T); + +public: + PbiField(size_t maxBufferSize) : maxElementCount_{maxBufferSize / ElementSize} + { + buffer_.reserve(maxElementCount_); + } + + void Add(T value) { buffer_.push_back(value); } + bool IsFull() const { return buffer_.size() == maxElementCount_; } + + size_t maxElementCount_; + std::vector buffer_; + std::vector blocks_; +}; +// -------------------------- +// PbiReferenceDataBuilder +// -------------------------- + +class PbiReferenceDataBuilder +{ +public: + using ReferenceRows = std::pair; // [startRow, endRow) + + explicit PbiReferenceDataBuilder(const size_t numReferenceSequences); + + bool AddRecord(const BamRecord& record, const int32_t rowNumber); + + PbiRawReferenceData Result() const; + + void WriteData(BGZF* bgzf); + +private: + int32_t lastRefId_ = -1; + Position lastPos_ = -1; + std::map rawReferenceEntries_; +}; + +PbiReferenceDataBuilder::PbiReferenceDataBuilder(const size_t numReferenceSequences) +{ + // initialize with number of references we expect to see + // + // we can add more later, but want to ensure known references have an entry + // even if no records are observed mapping to it + // + for (size_t i = 0; i < numReferenceSequences; ++i) + rawReferenceEntries_[i] = PbiReferenceEntry(i); + + // also create an "unmapped" entry + rawReferenceEntries_[PbiReferenceEntry::UNMAPPED_ID] = PbiReferenceEntry{}; +} + +bool PbiReferenceDataBuilder::AddRecord(const BamRecord& record, const int32_t rowNumber) +{ + // fetch ref ID & pos for record + const int32_t tId = record.ReferenceId(); + const int32_t pos = record.ReferenceStart(); + + // sanity checks to protect against non-coordinate-sorted BAMs + if (lastRefId_ != tId || (lastRefId_ >= 0 && tId < 0)) { + if (tId >= 0) { + + // if we've already seen unmapped reads, but our current tId is valid + // + // error: unmapped reads should all be at the end (can stop checking refs) + // + PbiReferenceEntry& unmappedEntry = + rawReferenceEntries_.at(PbiReferenceEntry::UNMAPPED_ID); + if (unmappedEntry.beginRow_ != PbiReferenceEntry::UNSET_ROW) return false; + + // if we've already seen data for this new tId + // (remember we're coming from another tId) + // + // error: refs are out of order (can stop checking refs) + // + PbiReferenceEntry& currentEntry = rawReferenceEntries_.at(static_cast(tId)); + if (currentEntry.beginRow_ != PbiReferenceEntry::UNSET_ROW) return false; + } + lastRefId_ = tId; + } else if (tId >= 0 && lastPos_ > pos) + return false; // error: positions out of order + + // update row numbers + PbiReferenceEntry& entry = rawReferenceEntries_.at(static_cast(tId)); + if (entry.beginRow_ == PbiReferenceEntry::UNSET_ROW) entry.beginRow_ = rowNumber; + entry.endRow_ = rowNumber + 1; + + // update pos (for sorting check next go-round) + lastPos_ = pos; + return true; +} + +PbiRawReferenceData PbiReferenceDataBuilder::Result() const +{ + // PbiReferenceEntries will be sorted thanks to std::map + // tId will be at end since we're sorting on the uint cast of -1 + PbiRawReferenceData result; + result.entries_.reserve(rawReferenceEntries_.size()); + for (const auto& entry : rawReferenceEntries_) + result.entries_.push_back(entry.second); + return result; +} + +void PbiReferenceDataBuilder::WriteData(BGZF* bgzf) +{ + const auto refData = Result(); + + // num_refs + uint32_t numRefs = refData.entries_.size(); + if (bgzf->is_be) numRefs = ed_swap_4(numRefs); + internal::bgzf_write_safe(bgzf, &numRefs, 4); + + // reference entries + numRefs = refData.entries_.size(); // need to reset after maybe endian-swapping + for (size_t i = 0; i < numRefs; ++i) { + auto& entry = refData.entries_[i]; + auto tId = entry.tId_; + auto beginRow = entry.beginRow_; + auto endRow = entry.endRow_; + if (bgzf->is_be) { + tId = ed_swap_4(tId); + beginRow = ed_swap_4(beginRow); + endRow = ed_swap_4(endRow); + } + internal::bgzf_write_safe(bgzf, &tId, 4); + internal::bgzf_write_safe(bgzf, &beginRow, 4); + internal::bgzf_write_safe(bgzf, &endRow, 4); + } +} + +} // namespace internal + +// -------------------------------------------- +// PbiBuilderPrivate - builder implementation +// -------------------------------------------- + +// TODO: Come back to refseqs, sorting, etc + +// TODO: We **NEED** to sync this up with the builder in IndexedBamWriter. They +// differ slightly but should be shareable. + +class PbiBuilder::PbiBuilderPrivate +{ + enum class FlushMode + { + FORCE, + NO_FORCE + }; + + // TODO: Make this tweak-able, a la IndexedBamWriter's buffers + constexpr static const size_t MaxBufferSize = 0x10000; + +public: + PbiBuilderPrivate(const std::string& pbiFilename, const size_t numReferenceSequences, + const bool isCoordinateSorted, + const PbiBuilder::CompressionLevel compressionLevel, const size_t numThreads) + : pbiFilename_{pbiFilename} + , tempFilename_{pbiFilename + ".build"} + , tempFile_{std::fopen(tempFilename_.c_str(), "w+b")} + , compressionLevel_{compressionLevel} + , numThreads_{numThreads} + , rgIdField_{MaxBufferSize} + , qStartField_{MaxBufferSize} + , qEndField_{MaxBufferSize} + , holeNumField_{MaxBufferSize} + , readQualField_{MaxBufferSize} + , ctxtField_{MaxBufferSize} + , fileOffsetField_{MaxBufferSize} + , tIdField_{MaxBufferSize} + , tStartField_{MaxBufferSize} + , tEndField_{MaxBufferSize} + , aStartField_{MaxBufferSize} + , aEndField_{MaxBufferSize} + , revStrandField_{MaxBufferSize} + , nMField_{MaxBufferSize} + , nMMField_{MaxBufferSize} + , mapQualField_{MaxBufferSize} + , bcForwardField_{MaxBufferSize} + , bcReverseField_{MaxBufferSize} + , bcQualField_{MaxBufferSize} + { + if (!tempFile_) + throw std::runtime_error{"PbiBuilder: could not open temp file: " + tempFilename_}; + + if (isCoordinateSorted && numReferenceSequences > 0) + refDataBuilder_ = + std::make_unique(numReferenceSequences); + } + + ~PbiBuilderPrivate() noexcept + { + if (!isClosed_) { + try { + Close(); + } catch (...) { + // swallow any exceptions & remain no-throw from dtor + } + } + } + + void AddRecord(const BamRecord& b, const int64_t uOffset) + { + // ensure updated data (necessary?) + PacBio::BAM::BamRecordMemory::UpdateRecordTags(b); + b.ResetCachedPositions(); + + // store record data & maybe flush to temp file + AddBasicData(b, uOffset); + AddMappedData(b); + AddBarcodeData(b); + AddReferenceData(b, currentRow_); + FlushBuffers(FlushMode::NO_FORCE); + + ++currentRow_; + } + + void AddBasicData(const BamRecord& b, const int64_t uOffset) + { + // read group ID + const auto rgId = [&b]() -> int32_t { + auto rgIdString = b.ReadGroupBaseId(); + if (rgIdString.empty()) rgIdString = MakeReadGroupId(b.MovieName(), ToString(b.Type())); + return std::stoul(rgIdString, nullptr, 16); + }(); + + // query start/end + const auto isCcsOrTranscript = (IsCcsOrTranscript(b.Type())); + const int32_t qStart = (isCcsOrTranscript ? 0 : b.QueryStart()); + const int32_t qEnd = (isCcsOrTranscript ? b.Impl().SequenceLength() : b.QueryEnd()); + + // add'l data + const int32_t holeNum = (b.HasHoleNumber() ? b.HoleNumber() : 0); + const float readAccuracy = + (b.HasReadAccuracy() ? boost::numeric_cast(b.ReadAccuracy()) : 0.0F); + const uint8_t ctxt = (b.HasLocalContextFlags() ? b.LocalContextFlags() + : LocalContextFlags::NO_LOCAL_CONTEXT); + + // store + rgIdField_.Add(rgId); + qStartField_.Add(qStart); + qEndField_.Add(qEnd); + holeNumField_.Add(holeNum); + ctxtField_.Add(ctxt); + readQualField_.Add(readAccuracy); + fileOffsetField_.Add(uOffset); + } + + void AddMappedData(const BamRecord& b) + { + // alignment position + const auto tId = b.ReferenceId(); + const auto tStart = static_cast(b.ReferenceStart()); + const auto tEnd = static_cast(b.ReferenceEnd()); + const auto aStart = static_cast(b.AlignedStart()); + const auto aEnd = static_cast(b.AlignedEnd()); + const auto isReverseStrand = [&b]() -> uint8_t { + return (b.AlignedStrand() == Strand::REVERSE ? 1 : 0); + }(); + + // alignment quality + const auto matchData = b.NumMatchesAndMismatches(); + const auto nM = static_cast(matchData.first); + const auto nMM = static_cast(matchData.second); + const auto mapQuality = b.MapQuality(); + + if (tId >= 0) hasMappedData_ = true; + + // store + tIdField_.Add(tId); + tStartField_.Add(tStart); + tEndField_.Add(tEnd); + aStartField_.Add(aStart); + aEndField_.Add(aEnd); + revStrandField_.Add(isReverseStrand); + nMField_.Add(nM); + nMMField_.Add(nMM); + mapQualField_.Add(mapQuality); + } + + void AddBarcodeData(const BamRecord& b) + { + // initialize w/ 'missing' value + int16_t bcForward = -1; + int16_t bcReverse = -1; + int8_t bcQuality = -1; + + // check for any barcode data (both required) + if (b.HasBarcodes() && b.HasBarcodeQuality()) { + // fetch data from record + std::tie(bcForward, bcReverse) = b.Barcodes(); + bcQuality = static_cast(b.BarcodeQuality()); + + // double-check & reset to 'missing' value if any less than zero + if (bcForward < 0 && bcReverse < 0 && bcQuality < 0) { + bcForward = -1; + bcReverse = -1; + bcQuality = -1; + } else + hasBarcodeData_ = true; + } + + // store + bcForwardField_.Add(bcForward); + bcReverseField_.Add(bcReverse); + bcQualField_.Add(bcQuality); + } + + void AddReferenceData(const BamRecord& b, const uint32_t currentRow) + { + // only add if coordinate-sorted hint is set + // update with info from refDataBuilder + if (refDataBuilder_) { + const auto sorted = refDataBuilder_->AddRecord(b, currentRow); + if (!sorted) refDataBuilder_.reset(); + } + } + + void Close() + { + if (isClosed_) return; + + FlushBuffers(FlushMode::FORCE); + + OpenPbiFile(); + WritePbiHeader(); + WriteFromTempFile(); + + remove(tempFilename_.c_str()); + isClosed_ = true; + } + + void OpenPbiFile() + { + // open file handle + const auto mode = std::string("wb") + std::to_string(static_cast(compressionLevel_)); + pbiFile_.reset(bgzf_open(pbiFilename_.c_str(), mode.c_str())); + if (pbiFile_ == nullptr) + throw std::runtime_error{"PbiBuilder: could not open file for writing: " + + pbiFilename_}; + + // if no explicit thread count given, attempt built-in check + size_t actualNumThreads = numThreads_; + if (actualNumThreads == 0) { + actualNumThreads = std::thread::hardware_concurrency(); + + // if still unknown, default to single-threaded + if (actualNumThreads == 0) actualNumThreads = 1; + } + + // if multithreading requested, enable it + if (actualNumThreads > 1) bgzf_mt(pbiFile_.get(), actualNumThreads, 256); + } + + template + void MaybeFlushBuffer(internal::PbiField& field, bool force) + { + // replace with lambda, in FlushBuffer(), once PPA can use C++14 ? + if (field.IsFull() || force) { + WriteToTempFile(field); + field.buffer_.clear(); + } + } + + void FlushBuffers(FlushMode mode) + { + const auto force = (mode == FlushMode::FORCE); + + MaybeFlushBuffer(rgIdField_, force); + MaybeFlushBuffer(qStartField_, force); + MaybeFlushBuffer(qEndField_, force); + MaybeFlushBuffer(holeNumField_, force); + MaybeFlushBuffer(readQualField_, force); + MaybeFlushBuffer(ctxtField_, force); + MaybeFlushBuffer(fileOffsetField_, force); + + MaybeFlushBuffer(tIdField_, force); + MaybeFlushBuffer(tStartField_, force); + MaybeFlushBuffer(tEndField_, force); + MaybeFlushBuffer(aStartField_, force); + MaybeFlushBuffer(aEndField_, force); + MaybeFlushBuffer(revStrandField_, force); + MaybeFlushBuffer(nMField_, force); + MaybeFlushBuffer(nMMField_, force); + MaybeFlushBuffer(mapQualField_, force); + + MaybeFlushBuffer(bcForwardField_, force); + MaybeFlushBuffer(bcReverseField_, force); + MaybeFlushBuffer(bcQualField_, force); + } + + template + void LoadFieldBlockFromTempFile(internal::PbiField& field, + const internal::PbiFieldBlock& block) + { + // seek to block begin + const auto ret = std::fseek(tempFile_.get(), block.pos_, SEEK_SET); + if (ret != 0) + throw std::runtime_error{"PbiBuilder: could not seek in temp file: " + tempFilename_ + + ", offset: " + std::to_string(block.pos_)}; + + // read block elements + field.buffer_.assign(block.n_, 0); + const auto numElements = + std::fread(field.buffer_.data(), sizeof(T), block.n_, tempFile_.get()); + + if (numElements != block.n_) + throw std::runtime_error{"PbiBuilder: could not read element count from temp file: " + + tempFilename_}; + } + + template + void WriteField(internal::PbiField& field) + { + for (const auto& block : field.blocks_) { + LoadFieldBlockFromTempFile(field, block); + internal::WriteBgzfVector(pbiFile_.get(), field.buffer_); + } + } + + void WriteFromTempFile() + { + // load from temp file, in PBI format order, and write to index + + WriteField(rgIdField_); + WriteField(qStartField_); + WriteField(qEndField_); + WriteField(holeNumField_); + WriteField(readQualField_); + WriteField(ctxtField_); + WriteField(fileOffsetField_); + + if (hasMappedData_) { + WriteField(tIdField_); + WriteField(tStartField_); + WriteField(tEndField_); + WriteField(aStartField_); + WriteField(aEndField_); + WriteField(revStrandField_); + WriteField(nMField_); + WriteField(nMMField_); + WriteField(mapQualField_); + } + + if (refDataBuilder_) WriteReferenceData(); + + if (hasBarcodeData_) { + WriteField(bcForwardField_); + WriteField(bcReverseField_); + WriteField(bcQualField_); + } + } + + template + void WriteToTempFile(internal::PbiField& field) + { + if (field.buffer_.empty()) return; + + const auto pos = std::ftell(tempFile_.get()); + const auto numElements = + std::fwrite(field.buffer_.data(), sizeof(T), field.buffer_.size(), tempFile_.get()); + field.blocks_.emplace_back(internal::PbiFieldBlock{pos, numElements}); + } + + void WritePbiHeader() + { + BGZF* bgzf = pbiFile_.get(); + + // 'magic' string + static constexpr const std::array magic{{'P', 'B', 'I', '\1'}}; + internal::bgzf_write_safe(bgzf, magic.data(), 4); + + PbiFile::Sections sections = PbiFile::BASIC; + if (hasMappedData_) sections |= PbiFile::MAPPED; + if (hasBarcodeData_) sections |= PbiFile::BARCODE; + if (refDataBuilder_) sections |= PbiFile::REFERENCE; + + // version, pbi_flags, & n_reads + auto version = static_cast(PbiFile::CurrentVersion); + uint16_t pbi_flags = sections; + auto numReads = currentRow_; + if (bgzf->is_be) { + version = ed_swap_4(version); + pbi_flags = ed_swap_2(pbi_flags); + numReads = ed_swap_4(numReads); + } + internal::bgzf_write_safe(bgzf, &version, 4); + internal::bgzf_write_safe(bgzf, &pbi_flags, 2); + internal::bgzf_write_safe(bgzf, &numReads, 4); + + // reserved space + char reserved[18]; + memset(reserved, 0, 18); + internal::bgzf_write_safe(bgzf, reserved, 18); + } + + void WriteReferenceData() { refDataBuilder_->WriteData(pbiFile_.get()); } + +private: + // file info + std::string bamFilename_; + std::string pbiFilename_; + std::string tempFilename_; + std::unique_ptr tempFile_; + std::unique_ptr pbiFile_; + PbiBuilder::CompressionLevel compressionLevel_; + size_t numThreads_; + + // PBI field buffers + internal::PbiField rgIdField_; + internal::PbiField qStartField_; + internal::PbiField qEndField_; + internal::PbiField holeNumField_; + internal::PbiField readQualField_; + internal::PbiField ctxtField_; + internal::PbiField fileOffsetField_; + internal::PbiField tIdField_; + internal::PbiField tStartField_; + internal::PbiField tEndField_; + internal::PbiField aStartField_; + internal::PbiField aEndField_; + internal::PbiField revStrandField_; + internal::PbiField nMField_; + internal::PbiField nMMField_; + internal::PbiField mapQualField_; + internal::PbiField bcForwardField_; + internal::PbiField bcReverseField_; + internal::PbiField bcQualField_; + + // reference data + std::unique_ptr refDataBuilder_; + + // tracking data + uint32_t currentRow_ = 0; + bool isClosed_ = false; + bool hasBarcodeData_ = false; + bool hasMappedData_ = false; +}; + +// -------------------------------------------- +// PbiBuilder - builder API +// -------------------------------------------- + +PbiBuilder::PbiBuilder(const std::string& pbiFilename, const CompressionLevel compressionLevel, + const size_t numThreads) + : PbiBuilder{pbiFilename, 0, false, compressionLevel, numThreads} +{ +} + +PbiBuilder::PbiBuilder(const std::string& pbiFilename, const size_t numReferenceSequences, + const CompressionLevel compressionLevel, const size_t numThreads) + : PbiBuilder{pbiFilename, numReferenceSequences, (numReferenceSequences > 0), compressionLevel, + numThreads} +{ +} + +PbiBuilder::PbiBuilder(const std::string& pbiFilename, const size_t numReferenceSequences, + const bool isCoordinateSorted, const CompressionLevel compressionLevel, + const size_t numThreads) + : d_{std::make_unique(pbiFilename, numReferenceSequences, isCoordinateSorted, + compressionLevel, numThreads)} +{ +} + +PbiBuilder::~PbiBuilder() noexcept = default; + +void PbiBuilder::AddRecord(const BamRecord& record, const int64_t vOffset) +{ + d_->AddRecord(record, vOffset); +} + +void PbiBuilder::Close() { d_->Close(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/PbiFile.cpp b/src/PbiFile.cpp new file mode 100644 index 0000000..fe5fdc0 --- /dev/null +++ b/src/PbiFile.cpp @@ -0,0 +1,37 @@ +// File Description +/// \file PbiFile.cpp +/// \brief Implements the PbiFile methods. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/PbiFile.h" + +#include +#include + +#include "pbbam/BamFile.h" +#include "pbbam/BamReader.h" +#include "pbbam/PbiBuilder.h" + +namespace PacBio { +namespace BAM { + +void PbiFile::CreateFrom(const BamFile& bamFile, + const PbiBuilder::CompressionLevel compressionLevel, + const size_t numThreads) +{ + PbiBuilder builder(bamFile.PacBioIndexFilename(), bamFile.Header().Sequences().size(), + compressionLevel, numThreads); + BamReader reader(bamFile); + BamRecord b; + int64_t offset = reader.VirtualTell(); + while (reader.GetNext(b)) { + builder.AddRecord(b, offset); + offset = reader.VirtualTell(); + } +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/PbiFilter.cpp b/src/PbiFilter.cpp new file mode 100644 index 0000000..5364f77 --- /dev/null +++ b/src/PbiFilter.cpp @@ -0,0 +1,497 @@ +// File Description +/// \file PbiFilter.cpp +/// \brief Implements the PbiFilter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/PbiFilter.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "FileUtils.h" +#include "pbbam/PbiFilterTypes.h" +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { +namespace internal { + +// clang-format off +enum class BuiltIn +{ + AlignedEndFilter + , AlignedLengthFilter + , AlignedStartFilter + , AlignedStrandFilter + , BarcodeFilter + , BarcodeForwardFilter + , BarcodeQualityFilter + , BarcodeReverseFilter + , BarcodesFilter + , IdentityFilter + , LocalContextFilter + , MovieNameFilter + , NumDeletedBasesFilter + , NumInsertedBasesFilter + , NumMatchesFilter + , NumMismatchesFilter + , QIdFilter + , QueryEndFilter + , QueryLengthFilter + , QueryNameFilter + , QueryNamesFromFileFilter + , QueryStartFilter + , ReadAccuracyFilter + , ReadGroupFilter + , ReferenceEndFilter + , ReferenceIdFilter + , ReferenceNameFilter + , ReferenceStartFilter + , ZmwFilter +}; + +static const std::unordered_map builtInLookup = +{ + // property name built-in filter + { "ae", BuiltIn::AlignedEndFilter }, + { "aend", BuiltIn::AlignedEndFilter }, + { "alignedlength", BuiltIn::AlignedLengthFilter }, + { "as", BuiltIn::AlignedStartFilter }, + { "astart", BuiltIn::AlignedStartFilter }, + { "readstart", BuiltIn::AlignedStartFilter }, + { "bc", BuiltIn::BarcodeFilter }, + { "barcode", BuiltIn::BarcodeFilter }, + { "bcf", BuiltIn::BarcodeForwardFilter }, + { "bq", BuiltIn::BarcodeQualityFilter }, + { "bcq", BuiltIn::BarcodeQualityFilter }, + { "bcr", BuiltIn::BarcodeReverseFilter }, + { "accuracy", BuiltIn::IdentityFilter }, + { "identity", BuiltIn::IdentityFilter }, + { "cx", BuiltIn::LocalContextFilter }, + { "movie", BuiltIn::MovieNameFilter }, + { "qid", BuiltIn::QIdFilter }, + { "qe", BuiltIn::QueryEndFilter }, + { "qend", BuiltIn::QueryEndFilter }, + { "length", BuiltIn::QueryLengthFilter }, + { "querylength", BuiltIn::QueryLengthFilter }, + { "qname", BuiltIn::QueryNameFilter }, + { "qname_file", BuiltIn::QueryNamesFromFileFilter }, + { "qs", BuiltIn::QueryStartFilter }, + { "qstart", BuiltIn::QueryStartFilter }, + { "rq", BuiltIn::ReadAccuracyFilter }, + { "te", BuiltIn::ReferenceEndFilter }, + { "tend", BuiltIn::ReferenceEndFilter }, + { "rname", BuiltIn::ReferenceNameFilter }, + { "ts", BuiltIn::ReferenceStartFilter }, + { "tstart", BuiltIn::ReferenceStartFilter }, + { "pos", BuiltIn::ReferenceStartFilter }, + { "zm", BuiltIn::ZmwFilter }, + { "zmw", BuiltIn::ZmwFilter } +}; + +static const std::unordered_map contextFlagNames = +{ + { "NO_LOCAL_CONTEXT", LocalContextFlags::NO_LOCAL_CONTEXT }, + { "ADAPTER_BEFORE", LocalContextFlags::ADAPTER_BEFORE }, + { "ADAPTER_AFTER", LocalContextFlags::ADAPTER_AFTER }, + { "BARCODE_BEFORE", LocalContextFlags::BARCODE_BEFORE }, + { "BARCODE_AFTER", LocalContextFlags::BARCODE_AFTER }, + { "FORWARD_PASS", LocalContextFlags::FORWARD_PASS }, + { "REVERSE_PASS", LocalContextFlags::REVERSE_PASS }, + { "ADAPTER_BEFORE_BAD", LocalContextFlags::ADAPTER_BEFORE_BAD}, + { "ADAPTER_AFTER_BAD", LocalContextFlags::ADAPTER_AFTER_BAD} +}; +// clang-format off + +// helper methods (for handling maybe-list strings)) +static inline bool isBracketed(const std::string& value) +{ + static const std::string openBrackets = "[({"; + static const std::string closeBrackets = "])}"; + return openBrackets.find(value.at(0)) != std::string::npos && + closeBrackets.find(value.at(value.length() - 1)) != std::string::npos; +} + +static inline bool isList(const std::string& value) { return value.find(',') != std::string::npos; } + +static PbiFilter CreateBarcodeFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for barcode filter property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + std::vector barcodes = Split(value, ','); + if (barcodes.size() != 2) throw std::runtime_error{"PbiFilter: only 2 barcode values expected"}; + return PbiBarcodesFilter{boost::numeric_cast(std::stoi(barcodes.at(0))), + boost::numeric_cast(std::stoi(barcodes.at(1))), + compareType}; + } else + return PbiBarcodeFilter{boost::numeric_cast(stoi(value)), compareType}; +} + +static PbiFilter CreateBarcodeForwardFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for barcode_forward filter property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + std::vector tokens = Split(value, ','); + std::vector barcodes; + barcodes.reserve(tokens.size()); + for (const auto& t : tokens) + barcodes.push_back(boost::numeric_cast(stoi(t))); + return PbiBarcodeForwardFilter{std::move(barcodes)}; + } else + return PbiBarcodeForwardFilter{boost::numeric_cast(std::stoi(value)), compareType}; +} + +static PbiFilter CreateBarcodeReverseFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for barcode_reverse filter property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + std::vector tokens = Split(value, ','); + std::vector barcodes; + barcodes.reserve(tokens.size()); + for (const auto& t : tokens) + barcodes.push_back(boost::numeric_cast(std::stoi(t))); + return PbiBarcodeReverseFilter{std::move(barcodes)}; + } else + return PbiBarcodeReverseFilter{boost::numeric_cast(stoi(value)), compareType}; +} + +static PbiFilter CreateLocalContextFilter(const std::string& value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for local context filter property"}; + + LocalContextFlags filterValue = LocalContextFlags::NO_LOCAL_CONTEXT; + + // if raw integer + if (isdigit(value.at(0))) filterValue = static_cast(stoi(value)); + + // else interpret as flag names + else { + std::vector tokens = Split(value, '|'); + for (std::string& token : tokens) { + boost::algorithm::trim(token); // trim whitespace + filterValue = (filterValue | contextFlagNames.at(token)); + } + } + + return PbiFilter{PbiLocalContextFilter{filterValue, compareType}}; +} + +static PbiFilter CreateMovieNameFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for movie property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + + if (compareType != Compare::EQUAL && compareType != Compare::NOT_EQUAL) + throw std::runtime_error{"PbiFilter: unsupported compare type on movie property"}; + + std::vector tokens = Split(value, ','); + return PbiMovieNameFilter{std::move(tokens), compareType}; + } else + return PbiMovieNameFilter{value, compareType}; +} + +static PbiFilter CreateQIdFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for qid property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + + if (compareType != Compare::EQUAL && compareType != Compare::NOT_EQUAL) + throw std::runtime_error{"PbiFilter: unsupported compare type on qid property"}; + + std::vector rgIds; + for (const auto& t : Split(value, ',')) + rgIds.push_back(static_cast(std::stoul(t))); + return PbiReadGroupFilter{rgIds, compareType}; + } else { + const auto n = static_cast(std::stoul(value)); + return PbiReadGroupFilter{n, compareType}; + } + +} + +static PbiFilter CreateQueryNamesFilterFromFile(const std::string& value, const DataSet& dataset, const Compare::Type compareType) +{ + if (compareType != Compare::EQUAL && compareType != Compare::NOT_EQUAL) + throw std::runtime_error{"PbiFilter: unsupported compare type on query name property"}; + + // resolve file from dataset, value + const std::string resolvedFilename = dataset.ResolvePath(value); + std::vector whitelist; + std::string fn; + std::ifstream in(resolvedFilename); + while (std::getline(in, fn)) + whitelist.push_back(fn); + return PbiQueryNameFilter{whitelist, compareType}; +} + +static PbiFilter CreateQueryNameFilter(std::string value, const DataSet& dataset, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for query name property"}; + + // try possible filename first + const std::string resolvedFilename = dataset.ResolvePath(value); + if (FileUtils::Exists(value)) + return CreateQueryNamesFilterFromFile(value, dataset, compareType); + + // otherwise "normal" qname (single, or list) + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + + if (compareType != Compare::EQUAL && compareType != Compare::NOT_EQUAL) + throw std::runtime_error{"PbiFilter: unsupported compare type on query name property"}; + + std::vector tokens = Split(value, ','); + return PbiQueryNameFilter{std::move(tokens), compareType}; + } else + return PbiQueryNameFilter{value, compareType}; +} + +static PbiFilter CreateReadGroupFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for read group property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + + if (compareType != Compare::EQUAL && compareType != Compare::NOT_EQUAL) + throw std::runtime_error{"PbiFilter: unsupported compare type on read group property"}; + + std::vector tokens = Split(value, ','); + return PbiReadGroupFilter{std::move(tokens), compareType}; + } else + return PbiReadGroupFilter{value, compareType}; +} + +static PbiFilter CreateReferenceIdFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for reference ID property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + + if (compareType != Compare::EQUAL && compareType != Compare::NOT_EQUAL) + throw std::runtime_error{"PbiFilter: unsupported compare type on reference name ID property"}; + + std::vector tokens = Split(value, ','); + std::vector ids; + ids.reserve(tokens.size()); + for (const auto& t : tokens) + ids.push_back(boost::numeric_cast(stoi(t))); + return PbiReferenceIdFilter{std::move(ids), compareType}; + } else + return PbiReferenceIdFilter{boost::numeric_cast(stoi(value)), compareType}; +} + +static PbiFilter CreateReferenceNameFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for reference name property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + + if (compareType != Compare::EQUAL && compareType != Compare::NOT_EQUAL) + throw std::runtime_error{"PbiFilter: unsupported compare type on reference name property"}; + + std::vector tokens = Split(value, ','); + return PbiReferenceNameFilter{std::move(tokens), compareType}; + } else + return PbiReferenceNameFilter{value, compareType}; +} + +static PbiFilter CreateZmwFilter(std::string value, const Compare::Type compareType) +{ + if (value.empty()) throw std::runtime_error{"PbiFilter: empty value for ZMW filter property"}; + + if (isBracketed(value)) { + value.erase(0, 1); + value.pop_back(); + } + + if (isList(value)) { + std::vector tokens = Split(value, ','); + std::vector zmws; + zmws.reserve(tokens.size()); + for (const auto& t : tokens) + zmws.push_back(boost::numeric_cast(stoi(t))); + return PbiZmwFilter{std::move(zmws)}; + } else + return PbiZmwFilter{boost::numeric_cast(stoi(value)), compareType}; +} + +static PbiFilter CreateZmwModuloFilter(const Property& property) +{ + if (!property.HasAttribute("Modulo") || !property.HasAttribute("Hash") || + property.Name() != "zm") + { + throw std::runtime_error{"PbiFilter: modulo filter is not supported on property: " + property.Name()}; + } + + const auto hashType = property.Attribute("Hash"); + const FilterHash hash = [&hashType]() + { + if (boost::algorithm::to_lower_copy(hashType) == "uint32cast") + return FilterHash::UNSIGNED_LONG_CAST; + if (boost::algorithm::to_lower_copy(hashType) == "boosthashcombine") + return FilterHash::BOOST_HASH_COMBINE; + throw std::runtime_error{"PbiFilter: unsuppoerted hash type: " + hashType}; + }(); + + const uint32_t denom = std::stoul(property.Attribute("Modulo")); + const uint32_t value = std::stoul(property.Value()); + + return PbiZmwModuloFilter{ denom, value, hash, Compare::EQUAL }; +} + +static PbiFilter FromDataSetProperty(const Property& property, const DataSet& dataset) +{ + try { + const std::string& value = property.Value(); + + if (property.Name() == "zm" && property.HasAttribute("Modulo")) + return CreateZmwModuloFilter(property); + + const Compare::Type compareType = Compare::TypeFromOperator(property.Operator()); + const BuiltIn builtInCode = + builtInLookup.at(boost::algorithm::to_lower_copy(property.Name())); + + // clang-format off + switch (builtInCode) { + + // single-value filters + case BuiltIn::AlignedEndFilter : return PbiAlignedEndFilter{ static_cast(std::stoul(value)), compareType }; + case BuiltIn::AlignedLengthFilter : return PbiAlignedLengthFilter{ static_cast(std::stoul(value)), compareType }; + case BuiltIn::AlignedStartFilter : return PbiAlignedStartFilter{ static_cast(std::stoul(value)), compareType }; + case BuiltIn::BarcodeQualityFilter : return PbiBarcodeQualityFilter{ static_cast(std::stoul(value)), compareType }; + case BuiltIn::IdentityFilter : return PbiIdentityFilter{ std::stof(value), compareType }; + case BuiltIn::QueryEndFilter : return PbiQueryEndFilter{ std::stoi(value), compareType }; + case BuiltIn::QueryLengthFilter : return PbiQueryLengthFilter{ std::stoi(value), compareType }; + case BuiltIn::QueryStartFilter : return PbiQueryStartFilter{ std::stoi(value), compareType }; + case BuiltIn::ReadAccuracyFilter : return PbiReadAccuracyFilter{ std::stof(value), compareType }; + case BuiltIn::ReferenceEndFilter : return PbiReferenceEndFilter{ static_cast(std::stoul(value)), compareType }; + case BuiltIn::ReferenceStartFilter : return PbiReferenceStartFilter{ static_cast(std::stoul(value)), compareType }; + + // (maybe) list-value filters + case BuiltIn::BarcodeFilter : return CreateBarcodeFilter(value, compareType); + case BuiltIn::BarcodeForwardFilter : return CreateBarcodeForwardFilter(value, compareType); + case BuiltIn::BarcodeReverseFilter : return CreateBarcodeReverseFilter(value, compareType); + case BuiltIn::LocalContextFilter : return CreateLocalContextFilter(value, compareType); + case BuiltIn::MovieNameFilter : return CreateMovieNameFilter(value, compareType); + case BuiltIn::QIdFilter : return CreateQIdFilter(value, compareType); + case BuiltIn::QueryNameFilter : return CreateQueryNameFilter(value, dataset, compareType); + case BuiltIn::ReadGroupFilter : return CreateReadGroupFilter(value, compareType); + case BuiltIn::ReferenceIdFilter : return CreateReferenceIdFilter(value, compareType); + case BuiltIn::ReferenceNameFilter : return CreateReferenceNameFilter(value, compareType); + case BuiltIn::ZmwFilter : return CreateZmwFilter(value, compareType); + + // other built-ins + case BuiltIn::QueryNamesFromFileFilter : return CreateQueryNamesFilterFromFile(value, dataset, compareType); + + default : + throw std::runtime_error{"PbiFilter: invalid built-in filter requested"}; + } + // clang-format on + + // unreachable + return PbiFilter{}; + + } catch (std::exception& e) { + std::ostringstream s; + s << "PbiFilter: could not create filter from XML Property element:\n" + << " Name: " << property.Name() << '\n' + << " Value: " << property.Value() << '\n' + << " Operator: " << property.Operator() << '\n' + << " reason: " << e.what() << '\n'; + throw std::runtime_error{s.str()}; + } +} + +} // namespace internal + +PbiFilter PbiFilter::FromDataSet(const DataSet& dataset) +{ + PbiFilter datasetFilter{PbiFilter::UNION}; + for (const auto& xmlFilter : dataset.Filters()) { + PbiFilter propertiesFilter; + for (const auto& xmlProperty : xmlFilter.Properties()) + propertiesFilter.Add(internal::FromDataSetProperty(xmlProperty, dataset)); + datasetFilter.Add(propertiesFilter); + } + return datasetFilter; +} + +PbiFilter PbiFilter::Intersection(std::vector filters) +{ + auto result = PbiFilter{PbiFilter::INTERSECT}; + result.Add(std::move(filters)); + return result; +} + +PbiFilter PbiFilter::Union(std::vector filters) +{ + auto result = PbiFilter{PbiFilter::UNION}; + result.Add(std::move(filters)); + return result; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/PbiFilterQuery.cpp b/src/PbiFilterQuery.cpp new file mode 100644 index 0000000..37d655f --- /dev/null +++ b/src/PbiFilterQuery.cpp @@ -0,0 +1,58 @@ +// File Description +/// \file PbiFilterQuery.cpp +/// \brief Implements the PbiFilterQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/PbiFilterQuery.h" + +#include + +#include "pbbam/CompositeBamReader.h" + +namespace PacBio { +namespace BAM { + +class PbiFilterQuery::PbiFilterQueryPrivate +{ +public: + PbiFilterQueryPrivate(const PbiFilter& filter, const DataSet& dataset, + const PbiIndexCache& cache) + : reader_{filter, dataset, cache} + { + } + + PbiFilterCompositeBamReader reader_; // unsorted +}; + +PbiFilterQuery::PbiFilterQuery(const DataSet& dataset) + : PbiFilterQuery{PbiFilter::FromDataSet(dataset), dataset, MakePbiIndexCache(dataset)} +{ +} + +PbiFilterQuery::PbiFilterQuery(const DataSet& dataset, const PbiIndexCache& cache) + : PbiFilterQuery{PbiFilter::FromDataSet(dataset), dataset, cache} +{ +} + +PbiFilterQuery::PbiFilterQuery(const PbiFilter& filter, const DataSet& dataset) + : PbiFilterQuery{filter, dataset, MakePbiIndexCache(dataset)} +{ +} + +PbiFilterQuery::PbiFilterQuery(const PbiFilter& filter, const DataSet& dataset, + const PbiIndexCache& cache) + : internal::IQuery(), d_{std::make_unique(filter, dataset, cache)} +{ +} + +PbiFilterQuery::~PbiFilterQuery() = default; + +bool PbiFilterQuery::GetNext(BamRecord& r) { return d_->reader_.GetNext(r); } + +uint32_t PbiFilterQuery::NumReads() const { return d_->reader_.NumReads(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/PbiFilterTypes.cpp b/src/PbiFilterTypes.cpp new file mode 100644 index 0000000..6cba0b1 --- /dev/null +++ b/src/PbiFilterTypes.cpp @@ -0,0 +1,522 @@ +// File Description +/// \file PbiFilterTypes.cpp +/// \brief Implements the built-in PBI filters. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/PbiFilterTypes.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { +namespace { + +template +IndexList readLengthHelper(const std::vector& start, const std::vector& end, const T& value, + const Compare::Type cmp) +{ + assert(start.size() == end.size()); + + auto result = IndexList{}; + const auto numElements = start.size(); + for (size_t i = 0; i < numElements; ++i) { + const auto readLength = end[i] - start[i]; + bool keep = false; + switch (cmp) { + case Compare::EQUAL: + keep = (readLength == value); + break; + case Compare::NOT_EQUAL: + keep = (readLength != value); + break; + case Compare::LESS_THAN: + keep = (readLength < value); + break; + case Compare::LESS_THAN_EQUAL: + keep = (readLength <= value); + break; + case Compare::GREATER_THAN: + keep = (readLength > value); + break; + case Compare::GREATER_THAN_EQUAL: + keep = (readLength >= value); + break; + default: + assert(false); + throw std::runtime_error{ + "PbiFilter: read length filter encountered unknown compare type: " + + Compare::TypeToName(cmp)}; + } + + if (keep) result.push_back(i); + } + return result; +} + +PbiFilter filterFromMovieName(const std::string& movieName, bool includeCcs) +{ + // + // All transcript-type reads (movieName == "transcript") have the same + // read group ID. Calculate once & and create filters from that ID. + // + if (movieName == "transcript") { + static const auto transcriptRgId = MakeReadGroupId("transcript", "TRANSCRIPT"); + return PbiFilter{PbiReadGroupFilter{transcriptRgId}}; + } + + // + // For all other movie names, we can't determine read type up front, so we'll match + // on any rgIds from a candidate list. + // + auto filter = PbiFilter{PbiFilter::UNION}; + filter.Add({PbiReadGroupFilter{MakeReadGroupId(movieName, "POLYMERASE")}, + PbiReadGroupFilter{MakeReadGroupId(movieName, "HQREGION")}, + PbiReadGroupFilter{MakeReadGroupId(movieName, "SUBREAD")}, + PbiReadGroupFilter{MakeReadGroupId(movieName, "SCRAP")}, + PbiReadGroupFilter{MakeReadGroupId(movieName, "UNKNOWN")}}); + if (includeCcs) filter.Add(PbiReadGroupFilter{MakeReadGroupId(movieName, "CCS")}); + + return filter; +} + +} // namespace + +// PbiAlignedLengthFilter + +bool PbiAlignedLengthFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + const auto& mappedData = idx.MappedData(); + const auto& aEnd = mappedData.aEnd_.at(row); + const auto& aStart = mappedData.aStart_.at(row); + const auto aLength = aEnd - aStart; + return CompareHelper(aLength); +} + +// PbiIdentityFilter + +bool PbiIdentityFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + const auto& mappedData = idx.MappedData(); + const auto& nMM = mappedData.nMM_.at(row); + const auto& nIndels = mappedData.NumDeletedAndInsertedBasesAt(row); + const auto& nDel = nIndels.first; + const auto& nIns = nIndels.second; + + const auto& basicData = idx.BasicData(); + const auto& qStart = basicData.qStart_.at(row); + const auto& qEnd = basicData.qEnd_.at(row); + + const float readLength = qEnd - qStart; + const float nonMatches = nMM + nDel + nIns; + const float identity = 1.0f - (nonMatches / readLength); + + return CompareHelper(identity); +} + +// PbiMovieNameFilter + +PbiMovieNameFilter::PbiMovieNameFilter(const std::string& movieName, const Compare::Type cmp) + : compositeFilter_{filterFromMovieName(movieName, true)} // include CCS + , cmp_{cmp} +{ +} + +PbiMovieNameFilter::PbiMovieNameFilter(const std::vector& movieNames, + const Compare::Type cmp) + : compositeFilter_{PbiFilter::UNION}, cmp_{cmp} +{ + for (const auto& movieName : movieNames) + compositeFilter_.Add(filterFromMovieName(movieName, true)); // include CCS +} + +// PbiQueryLengthFilter + +bool PbiQueryLengthFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + const auto& basicData = idx.BasicData(); + const auto& qStart = basicData.qStart_.at(row); + const auto& qEnd = basicData.qEnd_.at(row); + const auto readLength = qEnd - qStart; + return CompareHelper(readLength); +} + +// PbiQueryNameFilter + +struct PbiQueryNameFilter::PbiQueryNameFilterPrivate +{ +public: + using QueryInterval = std::pair; + using QueryIntervals = std::set; + using ZmwLookup = std::unordered_map; + using ZmwLookupPtr = std::shared_ptr; // may be shared by more than one rgId + using RgIdLookup = std::unordered_map; + + PbiQueryNameFilterPrivate(const std::vector& queryNames, + const Compare::Type cmp = Compare::EQUAL) + : cmp_{cmp} + { + for (const auto& queryName : queryNames) { + + if (queryName.find("transcript/") == 0) + HandleName(queryName, RecordType::TRANSCRIPT); + else if (queryName.find("/ccs") != std::string::npos) + HandleName(queryName, RecordType::CCS); + else + HandleName(queryName, RecordType::UNKNOWN); + } + } + + PbiQueryNameFilterPrivate(const std::unique_ptr& other) + { + if (other) { + lookup_ = other->lookup_; + cmp_ = other->cmp_; + } + } + + bool Accepts(const PbiRawData& idx, const size_t row) const + { + const auto& basicData = idx.BasicData(); + + const bool found = [&]() { + // see if row's RGID known + const auto& rgId = basicData.rgId_.at(row); + const auto rgFound = lookup_.find(rgId); + if (rgFound == lookup_.end()) return false; + + // see if row's ZMW known + const auto& zmwPtr = rgFound->second; + const auto zmw = basicData.holeNumber_.at(row); + const auto zmwFound = zmwPtr->find(zmw); + if (zmwFound == zmwPtr->end()) return false; + + // see if row's QueryStart/QueryEnd known + // CCS names already covered in lookup construction phase + const auto& queryIntervals = zmwFound->second; + const auto qStart = basicData.qStart_.at(row); + const auto qEnd = basicData.qEnd_.at(row); + const auto queryInterval = std::make_pair(qStart, qEnd); + return (queryIntervals.find(queryInterval) != queryIntervals.end()); + }(); + + if (cmp_ == Compare::EQUAL || cmp_ == Compare::CONTAINS) + return found; + else if (cmp_ == Compare::NOT_EQUAL || cmp_ == Compare::NOT_CONTAINS) + return !found; + else + throw std::runtime_error{"PbiFilter: unsupported compare type on query name filter"}; + } + + std::vector CandidateRgIds(const std::string& movieName, const RecordType type) + { + if (type == RecordType::CCS) + return {ReadGroupInfo::IdToInt(MakeReadGroupId(movieName, "CCS"))}; + + if (type == RecordType::TRANSCRIPT) + return {ReadGroupInfo::IdToInt(MakeReadGroupId(movieName, "TRANSCRIPT"))}; + + // we can't know for sure from QNAME alone + return {ReadGroupInfo::IdToInt(MakeReadGroupId(movieName, "POLYMERASE")), + ReadGroupInfo::IdToInt(MakeReadGroupId(movieName, "HQREGION")), + ReadGroupInfo::IdToInt(MakeReadGroupId(movieName, "SUBREAD")), + ReadGroupInfo::IdToInt(MakeReadGroupId(movieName, "SCRAP")), + ReadGroupInfo::IdToInt(MakeReadGroupId(movieName, "UNKNOWN")), + ReadGroupInfo::IdToInt(MakeReadGroupId(movieName, "ZMW"))}; + } + + void HandleName(const std::string& queryName, const RecordType type) + { + // split name into main parts + const auto nameParts = Split(queryName, '/'); + + // verify syntax + if (IsCcsOrTranscript(type)) { + if (nameParts.size() != 2) { + const auto typeName = (type == RecordType::CCS) ? "CCS" : "transcript"; + throw std::runtime_error{"PbiQueryNameFilter: requested QNAME (" + queryName + + ") is not valid for PacBio " + typeName + + " reads. See spec for details."}; + } + } else { + if (nameParts.size() != 3) { + throw std::runtime_error{"PbiQueryNameFilter: requested QNAME (" + queryName + + ") is not a valid PacBio BAM QNAME. See spec for details"}; + } + } + + // generate candidate read group IDs from movie name & record type, then + // add to lookup table + const auto zmwPtr = UpdateRgLookup(CandidateRgIds(nameParts.at(0), type)); + + // add qStart/qEnd interval to zmw lookup + const auto zmw = std::stoi(nameParts.at(1)); + if (IsCcsOrTranscript(type)) + UpdateZmwQueryIntervals(zmwPtr.get(), zmw, -1, -1); + else { + const auto queryIntervalParts = Split(nameParts.at(2), '_'); + if (queryIntervalParts.size() != 2) { + throw std::runtime_error{"PbiQueryNameFilter: requested QNAME (" + queryName + + ") is not a valid PacBio BAM QNAME. See spec for details"}; + } + UpdateZmwQueryIntervals(zmwPtr.get(), zmw, std::stoi(queryIntervalParts.at(0)), + std::stoi(queryIntervalParts.at(1))); + } + } + + ZmwLookupPtr UpdateRgLookup(std::vector&& rgIds) + { + assert(!rgIds.empty()); + + ZmwLookupPtr zmwPtr; + + const auto rgFound = lookup_.find(rgIds.front()); + if (rgFound == lookup_.end()) { + zmwPtr = std::make_shared(); + for (const auto& rg : rgIds) { + assert(lookup_.find(rg) == lookup_.end()); + lookup_.emplace(rg, zmwPtr); + } + } else { +#ifndef NDEBUG + for (const auto& rg : rgIds) + assert(lookup_.find(rg) != lookup_.end()); +#endif + zmwPtr = rgFound->second; + } + return zmwPtr; + } + + // add QS/QE pair to ZMW lookup + void UpdateZmwQueryIntervals(ZmwLookup* const zmwPtr, const int32_t zmw, + const int32_t queryStart, const int32_t queryEnd) + { + const auto zmwFound = zmwPtr->find(zmw); + if (zmwFound == zmwPtr->end()) zmwPtr->emplace(zmw, QueryIntervals{}); + auto& queryIntervals = zmwPtr->at(zmw); + queryIntervals.emplace(std::make_pair(queryStart, queryEnd)); + } + +private: + RgIdLookup lookup_; + Compare::Type cmp_; +}; + +PbiQueryNameFilter::PbiQueryNameFilter(const std::string& qname, const Compare::Type cmp) + : d_{std::make_unique( + std::vector{1, qname}, cmp)} +{ +} + +PbiQueryNameFilter::PbiQueryNameFilter(const std::vector& queryNames, + const Compare::Type cmp) + : d_{std::make_unique(queryNames, cmp)} +{ +} + +PbiQueryNameFilter::PbiQueryNameFilter(const PbiQueryNameFilter& other) + : d_{std::make_unique(other.d_)} +{ +} + +PbiQueryNameFilter::~PbiQueryNameFilter() = default; + +bool PbiQueryNameFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + return d_->Accepts(idx, row); +} + +// PbiReadGroupFilter + +PbiReadGroupFilter::PbiReadGroupFilter(const std::vector& rgIds, const Compare::Type cmp) + : cmp_{cmp} +{ + if (cmp_ == Compare::EQUAL) + cmp_ = Compare::CONTAINS; + else if (cmp_ == Compare::NOT_EQUAL) + cmp_ = Compare::NOT_CONTAINS; + + if (cmp_ != Compare::CONTAINS && cmp_ != Compare::NOT_CONTAINS) { + throw std::runtime_error{ + "PbiFilter: unsupported compare type (" + Compare::TypeToName(cmp) + + ") for this property. " + "Read group filter can only compare equality or presence in whitelist/blacklist."}; + } + + // Add RG ID & empty filter if not present. The empty filter will work for + // non-barcoded IDs that match the expected number(s). + // + for (const auto& rgId : rgIds) { + const auto found = lookup_.find(rgId); + if (found == lookup_.cend()) lookup_.emplace(rgId, boost::none); + } +} + +PbiReadGroupFilter::PbiReadGroupFilter(const int32_t rgId, const Compare::Type cmp) + : PbiReadGroupFilter{std::vector{rgId}, cmp} +{ +} + +PbiReadGroupFilter::PbiReadGroupFilter(const std::vector& readGroups, + const Compare::Type cmp) + : cmp_{cmp} +{ + if (cmp_ == Compare::EQUAL) + cmp_ = Compare::CONTAINS; + else if (cmp_ == Compare::NOT_EQUAL) + cmp_ = Compare::NOT_CONTAINS; + + if (cmp_ != Compare::CONTAINS && cmp_ != Compare::NOT_CONTAINS) { + throw std::runtime_error{ + "PbiFilter: unsupported compare type (" + Compare::TypeToName(cmp) + + ") for this property. " + "Read group filter can only compare equality or presence in whitelist/blacklist."}; + } + + for (const auto& rg : readGroups) { + // Add RG base ID with no filter if not present. The empty filter will + // work for non-barcoded IDs. We'll add to it if the base read group ID + // also has barcode labels,so that any barcode pair whitelisted for this + // read group filter will be a match. + // + const auto idNum = ReadGroupInfo::IdToInt(rg.BaseId()); + const auto found = lookup_.find(idNum); + if (found == lookup_.cend()) lookup_.emplace(idNum, boost::none); + + // Maybe add barcodes to base ID + const auto barcodes = rg.Barcodes(); + if (barcodes) { + const auto bcFor = static_cast(barcodes->first); + const auto bcRev = static_cast(barcodes->second); + auto& idBarcodes = lookup_.at(idNum); + if (!idBarcodes) idBarcodes = std::vector>{}; + idBarcodes->push_back(std::make_pair(bcFor, bcRev)); + } + } +} + +PbiReadGroupFilter::PbiReadGroupFilter(const ReadGroupInfo& rg, const Compare::Type cmp) + : PbiReadGroupFilter{std::vector{rg}, cmp} +{ +} + +PbiReadGroupFilter::PbiReadGroupFilter(const std::vector& rgIds, + const Compare::Type cmp) +{ + std::vector readGroups; + for (const auto rgId : rgIds) + readGroups.push_back(rgId); + *this = PbiReadGroupFilter{readGroups, cmp}; +} + +PbiReadGroupFilter::PbiReadGroupFilter(const std::string& rgId, const Compare::Type cmp) + : PbiReadGroupFilter{ReadGroupInfo{rgId}, cmp} +{ +} + +bool PbiReadGroupFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + const auto accepted = [this](const PbiRawData& index, const size_t i) { + // Check that read group base ID is found. + const auto rowRgId = index.BasicData().rgId_.at(i); + const auto foundAt = lookup_.find(rowRgId); + if (foundAt == lookup_.cend()) return false; + + // Read group's base ID is found, check for filtered barcodes. + // + // For non-barcoded read groups, the filter is empty. This is + // essentially a no-op for allowing all candidate rows. + // + const auto& barcodes = foundAt->second; + if (!barcodes) return true; + + // Return success on first match, otherwise no match found. + for (const auto bcPair : *barcodes) { + if (index.BarcodeData().bcForward_.at(i) == bcPair.first && + index.BarcodeData().bcReverse_.at(i) == bcPair.second) { + return true; + } + } + return false; + }(idx, row); + + assert(cmp_ == Compare::CONTAINS || cmp_ == Compare::NOT_CONTAINS); + return (cmp_ == Compare::CONTAINS ? accepted : !accepted); +} + +// PbiReferenceNameFilter + +PbiReferenceNameFilter::PbiReferenceNameFilter(std::string rname, Compare::Type cmp) + : rname_{std::move(rname)}, cmp_{cmp} +{ + Validate(); +} + +PbiReferenceNameFilter::PbiReferenceNameFilter(std::vector rnames, + const Compare::Type cmp) + : rnameWhitelist_{std::move(rnames)}, cmp_{cmp} +{ + Validate(); +} + +bool PbiReferenceNameFilter::Accepts(const PbiRawData& idx, const size_t row) const +{ + if (!initialized_) Initialize(idx); + return subFilter_.Accepts(idx, row); +} + +void PbiReferenceNameFilter::Initialize(const PbiRawData& idx) const +{ + + // fetch BAM header info associate with this index + const auto pbiFilename = idx.Filename(); + const auto bamFilename = pbiFilename.substr(0, pbiFilename.length() - 4); + const BamFile bamFile{bamFilename}; + + // single-value + if (rnameWhitelist_ == boost::none) { + const auto tId = bamFile.ReferenceId(rname_); + subFilter_ = PbiReferenceIdFilter{tId, cmp_}; + } + + // multi-value (whitelist/blacklist) + else { + std::vector ids; + for (const auto& rname : rnameWhitelist_.get()) + ids.push_back(bamFile.ReferenceId(rname)); + subFilter_ = PbiReferenceIdFilter{std::move(ids), cmp_}; + } + initialized_ = true; +} + +void PbiReferenceNameFilter::Validate() const +{ + // double-check valid compare type + const bool compareTypeOk = [&]() { + if (cmp_ == Compare::EQUAL) return true; + if (cmp_ == Compare::NOT_EQUAL) return true; + if (cmp_ == Compare::CONTAINS) return true; + if (cmp_ == Compare::NOT_CONTAINS) return true; + return false; + }(); + if (!compareTypeOk) { + throw std::runtime_error{ + "PbiFilter: unsupported compare type (" + Compare::TypeToName(cmp_) + + ") for this property. " + "Reference name filter can only compare equality or presence in whitelist/blacklist."}; + } +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/PbiIndexIO.cpp b/src/PbiIndexIO.cpp new file mode 100644 index 0000000..2afdcba --- /dev/null +++ b/src/PbiIndexIO.cpp @@ -0,0 +1,401 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "PbiIndexIO.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "MemoryUtils.h" +#include "pbbam/BamFile.h" +#include "pbbam/BamRecord.h" +#include "pbbam/EntireFileQuery.h" +#include "pbbam/PbiBuilder.h" + +namespace PacBio { +namespace BAM { +namespace { + +void CheckContainer(const std::string& container, const size_t expected, const size_t observed) +{ + if (observed != expected) { + std::ostringstream msg; + msg << "PBI index error: expected " << expected << " records in " << container + << " field, but found " << observed << " instead"; + throw std::runtime_error{msg.str()}; + } +} + +void CheckExpectedSize(const PbiRawBarcodeData& barcodeData, const size_t numReads) +{ + CheckContainer("BarcodeData.bc_forward", numReads, barcodeData.bcForward_.size()); + CheckContainer("BarcodeData.bc_reverse", numReads, barcodeData.bcReverse_.size()); + CheckContainer("BarcodeData.bc_qual", numReads, barcodeData.bcReverse_.size()); +} + +void CheckExpectedSize(const PbiRawBasicData& basicData, const size_t numReads) +{ + CheckContainer("BasicData.rgId", numReads, basicData.rgId_.size()); + CheckContainer("BasicData.qStart", numReads, basicData.qStart_.size()); + CheckContainer("BasicData.qEnd", numReads, basicData.qEnd_.size()); + CheckContainer("BasicData.holeNumber", numReads, basicData.holeNumber_.size()); + CheckContainer("BasicData.readQual", numReads, basicData.readQual_.size()); + CheckContainer("BasicData.ctxt_flag", numReads, basicData.ctxtFlag_.size()); + CheckContainer("BasicData.fileOffset", numReads, basicData.fileOffset_.size()); +} + +void CheckExpectedSize(const PbiRawMappedData& mappedData, const size_t numReads) +{ + CheckContainer("MappedData.tId", numReads, mappedData.tId_.size()); + CheckContainer("MappedData.tStart", numReads, mappedData.tStart_.size()); + CheckContainer("MappedData.tEnd", numReads, mappedData.tEnd_.size()); + CheckContainer("MappedData.aStart", numReads, mappedData.aStart_.size()); + CheckContainer("MappedData.aEnd", numReads, mappedData.aEnd_.size()); + CheckContainer("MappedData.revStrand", numReads, mappedData.revStrand_.size()); + CheckContainer("MappedData.nM", numReads, mappedData.nM_.size()); + CheckContainer("MappedData.nMM", numReads, mappedData.nMM_.size()); + CheckContainer("MappedData.mapQV", numReads, mappedData.mapQV_.size()); +} + +} // namespace + +PbiRawData PbiIndexIO::Load(const std::string& pbiFilename) +{ + PbiRawData rawData; + Load(rawData, pbiFilename); + return rawData; +} + +void PbiIndexIO::Load(PbiRawData& rawData, const std::string& filename) +{ + // open file for reading + if (!boost::algorithm::iends_with(filename, ".pbi")) + throw std::runtime_error{"unsupported file extension on " + filename}; + std::unique_ptr bgzf(bgzf_open(filename.c_str(), "rb")); + auto* fp = bgzf.get(); + if (fp == nullptr) + throw std::runtime_error{"could not open PBI file: " + filename + "for reading"}; + + // load data + LoadHeader(rawData, fp); + const auto numReads = rawData.NumReads(); + if (numReads > 0) { + LoadBasicData(rawData.BasicData(), numReads, fp); + if (rawData.HasMappedData()) LoadMappedData(rawData.MappedData(), numReads, fp); + if (rawData.HasReferenceData()) LoadReferenceData(rawData.ReferenceData(), fp); + if (rawData.HasBarcodeData()) LoadBarcodeData(rawData.BarcodeData(), numReads, fp); + } +} + +void PbiIndexIO::LoadFromDataSet(PbiRawData& aggregateData, const DataSet& dataset) +{ + aggregateData.NumReads(0); + aggregateData.FileSections(PbiFile::BASIC | PbiFile::MAPPED | PbiFile::BARCODE); + aggregateData.Version(PbiFile::CurrentVersion); + + const auto bamFiles = dataset.BamFiles(); + uint16_t fileNumber = 0; + for (const auto& bamFile : bamFiles) { + PbiRawData currentPbi{bamFile.PacBioIndexFilename()}; + const auto currentPbiCount = currentPbi.NumReads(); + + // read count + aggregateData.NumReads(aggregateData.NumReads() + currentPbiCount); + + // BasicData + auto& aggregateBasicData = aggregateData.BasicData(); + auto& currentBasicData = currentPbi.BasicData(); + Utility::MoveAppend(std::move(currentBasicData.rgId_), aggregateBasicData.rgId_); + Utility::MoveAppend(std::move(currentBasicData.qStart_), aggregateBasicData.qStart_); + Utility::MoveAppend(std::move(currentBasicData.qEnd_), aggregateBasicData.qEnd_); + Utility::MoveAppend(std::move(currentBasicData.holeNumber_), + aggregateBasicData.holeNumber_); + Utility::MoveAppend(std::move(currentBasicData.readQual_), aggregateBasicData.readQual_); + Utility::MoveAppend(std::move(currentBasicData.ctxtFlag_), aggregateBasicData.ctxtFlag_); + Utility::MoveAppend(std::move(currentBasicData.fileOffset_), + aggregateBasicData.fileOffset_); + Utility::MoveAppend(std::vector(currentPbiCount, fileNumber), + aggregateBasicData.fileNumber_); + + // BarcodeData + auto& aggregateBarcodeData = aggregateData.BarcodeData(); + if (currentPbi.HasBarcodeData()) { + auto& currentBarcodeData = currentPbi.BarcodeData(); + Utility::MoveAppend(std::move(currentBarcodeData.bcForward_), + aggregateBarcodeData.bcForward_); + Utility::MoveAppend(std::move(currentBarcodeData.bcReverse_), + aggregateBarcodeData.bcReverse_); + Utility::MoveAppend(std::move(currentBarcodeData.bcQual_), + aggregateBarcodeData.bcQual_); + } else { + Utility::MoveAppend(std::vector(currentPbiCount, -1), + aggregateBarcodeData.bcForward_); + Utility::MoveAppend(std::vector(currentPbiCount, -1), + aggregateBarcodeData.bcReverse_); + Utility::MoveAppend(std::vector(currentPbiCount, -1), + aggregateBarcodeData.bcQual_); + } + + // MappedData + auto& aggregateMappedData = aggregateData.MappedData(); + if (currentPbi.HasMappedData()) { + auto& currentMappedData = currentPbi.MappedData(); + Utility::MoveAppend(std::move(currentMappedData.tId_), aggregateMappedData.tId_); + Utility::MoveAppend(std::move(currentMappedData.tStart_), aggregateMappedData.tStart_); + Utility::MoveAppend(std::move(currentMappedData.tEnd_), aggregateMappedData.tEnd_); + Utility::MoveAppend(std::move(currentMappedData.aStart_), aggregateMappedData.aStart_); + Utility::MoveAppend(std::move(currentMappedData.aEnd_), aggregateMappedData.aEnd_); + Utility::MoveAppend(std::move(currentMappedData.revStrand_), + aggregateMappedData.revStrand_); + Utility::MoveAppend(std::move(currentMappedData.nM_), aggregateMappedData.nM_); + Utility::MoveAppend(std::move(currentMappedData.nMM_), aggregateMappedData.nMM_); + Utility::MoveAppend(std::move(currentMappedData.mapQV_), aggregateMappedData.mapQV_); + } else { + Utility::MoveAppend(std::vector(currentPbiCount, -1), + aggregateMappedData.tId_); + Utility::MoveAppend(std::vector(currentPbiCount, UnmappedPosition), + aggregateMappedData.tStart_); + Utility::MoveAppend(std::vector(currentPbiCount, UnmappedPosition), + aggregateMappedData.tEnd_); + Utility::MoveAppend(std::vector(currentPbiCount, UnmappedPosition), + aggregateMappedData.aStart_); + Utility::MoveAppend(std::vector(currentPbiCount, UnmappedPosition), + aggregateMappedData.aEnd_); + Utility::MoveAppend(std::vector(currentPbiCount, 0), + aggregateMappedData.revStrand_); + Utility::MoveAppend(std::vector(currentPbiCount, 0), aggregateMappedData.nM_); + Utility::MoveAppend(std::vector(currentPbiCount, 0), + aggregateMappedData.nMM_); + Utility::MoveAppend(std::vector(currentPbiCount, 255), + aggregateMappedData.mapQV_); + } + + ++fileNumber; + } +} + +void PbiIndexIO::LoadBarcodeData(PbiRawBarcodeData& barcodeData, const uint32_t numReads, BGZF* fp) +{ + // read from file + LoadBgzfVector(fp, barcodeData.bcForward_, numReads); + LoadBgzfVector(fp, barcodeData.bcReverse_, numReads); + LoadBgzfVector(fp, barcodeData.bcQual_, numReads); + + // validate + CheckExpectedSize(barcodeData, numReads); +} + +void PbiIndexIO::LoadHeader(PbiRawData& index, BGZF* fp) +{ + // 'magic' string + char magic[4]; + auto bytesRead = bgzf_read(fp, magic, 4); + if (bytesRead != 4 || strncmp(magic, "PBI\1", 4)) + throw std::runtime_error{"expected PBI file, found unknown format instead"}; + + // version, pbi_flags, & n_reads + uint32_t version; + uint16_t sections; + uint32_t numReads; + bytesRead = bgzf_read(fp, &version, sizeof(version)); + bytesRead = bgzf_read(fp, §ions, sizeof(sections)); + bytesRead = bgzf_read(fp, &numReads, sizeof(numReads)); + if (fp->is_be) { + version = ed_swap_4(version); + sections = ed_swap_2(sections); + numReads = ed_swap_4(numReads); + } + + index.Version(PbiFile::VersionEnum(version)); + index.FileSections(sections); + index.NumReads(numReads); + + // skip reserved section + size_t reservedLength = 18; + // adjust depending on version + char reserved[18]; + bytesRead = bgzf_read(fp, &reserved, reservedLength); +} + +void PbiIndexIO::LoadMappedData(PbiRawMappedData& mappedData, const uint32_t numReads, BGZF* fp) +{ + // read from file + LoadBgzfVector(fp, mappedData.tId_, numReads); + LoadBgzfVector(fp, mappedData.tStart_, numReads); + LoadBgzfVector(fp, mappedData.tEnd_, numReads); + LoadBgzfVector(fp, mappedData.aStart_, numReads); + LoadBgzfVector(fp, mappedData.aEnd_, numReads); + LoadBgzfVector(fp, mappedData.revStrand_, numReads); + LoadBgzfVector(fp, mappedData.nM_, numReads); + LoadBgzfVector(fp, mappedData.nMM_, numReads); + LoadBgzfVector(fp, mappedData.mapQV_, numReads); + + // validate + CheckExpectedSize(mappedData, numReads); +} + +void PbiIndexIO::LoadReferenceData(PbiRawReferenceData& referenceData, BGZF* fp) +{ + assert(sizeof(PbiReferenceEntry::ID) == 4); + assert(sizeof(PbiReferenceEntry::Row) == 4); + + // num refs + uint32_t numRefs; + auto ret = bgzf_read(fp, &numRefs, 4); + if (fp->is_be) numRefs = ed_swap_4(numRefs); + + // reference entries + referenceData.entries_.clear(); + referenceData.entries_.resize(numRefs); + for (auto& entry : referenceData.entries_) { + ret = bgzf_read(fp, &entry.tId_, 4); + ret = bgzf_read(fp, &entry.beginRow_, 4); + ret = bgzf_read(fp, &entry.endRow_, 4); + if (fp->is_be) { + entry.tId_ = ed_swap_4(entry.tId_); + entry.beginRow_ = ed_swap_4(entry.beginRow_); + entry.endRow_ = ed_swap_4(entry.endRow_); + } + } + UNUSED(ret); +} + +void PbiIndexIO::LoadBasicData(PbiRawBasicData& basicData, const uint32_t numReads, BGZF* fp) +{ + // read from file + LoadBgzfVector(fp, basicData.rgId_, numReads); + LoadBgzfVector(fp, basicData.qStart_, numReads); + LoadBgzfVector(fp, basicData.qEnd_, numReads); + LoadBgzfVector(fp, basicData.holeNumber_, numReads); + LoadBgzfVector(fp, basicData.readQual_, numReads); + LoadBgzfVector(fp, basicData.ctxtFlag_, numReads); + LoadBgzfVector(fp, basicData.fileOffset_, numReads); + + // validate + CheckExpectedSize(basicData, numReads); +} + +void PbiIndexIO::Save(const PbiRawData& index, const std::string& filename) +{ + std::unique_ptr bgzf(bgzf_open(filename.c_str(), "wb")); + auto* fp = bgzf.get(); + if (fp == nullptr) + throw std::runtime_error{"could not open PBI file: " + filename + "for writing"}; + + WriteHeader(index, fp); + const auto numReads = index.NumReads(); + if (numReads > 0) { + WriteBasicData(index.BasicData(), numReads, fp); + + if (index.HasMappedData()) WriteMappedData(index.MappedData(), numReads, fp); + if (index.HasReferenceData()) WriteReferenceData(index.ReferenceData(), fp); + if (index.HasBarcodeData()) WriteBarcodeData(index.BarcodeData(), numReads, fp); + } +} + +void PbiIndexIO::WriteBarcodeData(const PbiRawBarcodeData& barcodeData, const uint32_t numReads, + BGZF* fp) +{ + // validate + CheckExpectedSize(barcodeData, numReads); + + // write to file + WriteBgzfVector(fp, barcodeData.bcForward_); + WriteBgzfVector(fp, barcodeData.bcReverse_); + WriteBgzfVector(fp, barcodeData.bcQual_); +} + +void PbiIndexIO::WriteHeader(const PbiRawData& index, BGZF* fp) +{ + // 'magic' string + constexpr static const std::array magic{{'P', 'B', 'I', '\1'}}; + auto ret = bgzf_write(fp, magic.data(), 4); + + // version, pbi_flags, & n_reads + auto version = static_cast(index.Version()); + uint16_t pbi_flags = index.FileSections(); + auto numReads = static_cast(index.NumReads()); + if (fp->is_be) { + version = ed_swap_4(version); + pbi_flags = ed_swap_2(pbi_flags); + numReads = ed_swap_4(numReads); + } + ret = bgzf_write(fp, &version, 4); + ret = bgzf_write(fp, &pbi_flags, 2); + ret = bgzf_write(fp, &numReads, 4); + + // reserved space + char reserved[18]; + memset(reserved, 0, 18); + ret = bgzf_write(fp, reserved, 18); + UNUSED(ret); +} + +void PbiIndexIO::WriteMappedData(const PbiRawMappedData& mappedData, const uint32_t numReads, + BGZF* fp) +{ + // validate + CheckExpectedSize(mappedData, numReads); + + // write to file + WriteBgzfVector(fp, mappedData.tId_); + WriteBgzfVector(fp, mappedData.tStart_); + WriteBgzfVector(fp, mappedData.tEnd_); + WriteBgzfVector(fp, mappedData.aStart_); + WriteBgzfVector(fp, mappedData.aEnd_); + WriteBgzfVector(fp, mappedData.revStrand_); + WriteBgzfVector(fp, mappedData.nM_); + WriteBgzfVector(fp, mappedData.nMM_); + WriteBgzfVector(fp, mappedData.mapQV_); +} + +void PbiIndexIO::WriteReferenceData(const PbiRawReferenceData& referenceData, BGZF* fp) +{ + // num_refs + auto numRefs = referenceData.entries_.size(); + if (fp->is_be) numRefs = ed_swap_4(numRefs); + auto ret = bgzf_write(fp, &numRefs, 4); + + // reference entries + for (const auto& entry : referenceData.entries_) { + auto tId = entry.tId_; + auto beginRow = entry.beginRow_; + auto endRow = entry.endRow_; + if (fp->is_be) { + tId = ed_swap_4(tId); + beginRow = ed_swap_4(beginRow); + endRow = ed_swap_4(endRow); + } + ret = bgzf_write(fp, &tId, 4); + ret = bgzf_write(fp, &beginRow, 4); + ret = bgzf_write(fp, &endRow, 4); + } + UNUSED(ret); +} + +void PbiIndexIO::WriteBasicData(const PbiRawBasicData& basicData, const uint32_t numReads, BGZF* fp) +{ + // validate + CheckExpectedSize(basicData, numReads); + + // write to file + WriteBgzfVector(fp, basicData.rgId_); + WriteBgzfVector(fp, basicData.qStart_); + WriteBgzfVector(fp, basicData.qEnd_); + WriteBgzfVector(fp, basicData.holeNumber_); + WriteBgzfVector(fp, basicData.readQual_); + WriteBgzfVector(fp, basicData.ctxtFlag_); + WriteBgzfVector(fp, basicData.fileOffset_); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/PbiIndexIO.h b/src/PbiIndexIO.h new file mode 100644 index 0000000..cedfc63 --- /dev/null +++ b/src/PbiIndexIO.h @@ -0,0 +1,115 @@ +// Author: Derek Barnett + +#ifndef PBIINDEXIO_H +#define PBIINDEXIO_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pbbam/BamFile.h" +#include "pbbam/DataSet.h" +#include "pbbam/PbiFile.h" +#include "pbbam/PbiRawData.h" +#include "pbbam/Unused.h" + +namespace PacBio { +namespace BAM { + +class PbiIndexIO +{ +public: + // top-level entry points + static PbiRawData Load(const std::string& filename); + static void Load(PbiRawData& rawData, const std::string& filename); + static void LoadFromDataSet(PbiRawData& aggregateData, const DataSet& dataset); + static void Save(const PbiRawData& rawData, const std::string& filename); + + // per-component load + static void LoadBarcodeData(PbiRawBarcodeData& barcodeData, const uint32_t numReads, BGZF* fp); + static void LoadHeader(PbiRawData& index, BGZF* fp); + static void LoadMappedData(PbiRawMappedData& mappedData, const uint32_t numReads, BGZF* fp); + static void LoadReferenceData(PbiRawReferenceData& referenceData, BGZF* fp); + static void LoadBasicData(PbiRawBasicData& basicData, const uint32_t numReads, BGZF* fp); + + // per-data-field load + template + static void LoadBgzfVector(BGZF* fp, std::vector& data, const uint32_t numReads); + + // per-component write + static void WriteBarcodeData(const PbiRawBarcodeData& barcodeData, const uint32_t numReads, + BGZF* fp); + static void WriteHeader(const PbiRawData& index, BGZF* fp); + static void WriteMappedData(const PbiRawMappedData& mappedData, const uint32_t numReads, + BGZF* fp); + static void WriteReferenceData(const PbiRawReferenceData& referenceData, BGZF* fp); + static void WriteBasicData(const PbiRawBasicData& subreadData, const uint32_t numReads, + BGZF* fp); + + // per-data-field write + template + static void WriteBgzfVector(BGZF* fp, const std::vector& data); + +private: + // helper functions + template + static void SwapEndianness(std::vector& data); +}; + +template +inline void PbiIndexIO::LoadBgzfVector(BGZF* fp, std::vector& data, const uint32_t numReads) +{ + assert(fp); + data.resize(numReads); + auto ret = bgzf_read(fp, &data[0], numReads * sizeof(T)); + if (fp->is_be) SwapEndianness(data); + UNUSED(ret); +} + +template +inline void PbiIndexIO::SwapEndianness(std::vector& data) +{ + const auto elementSize = sizeof(T); + const auto numReads = data.size(); + switch (elementSize) { + case 1: + break; // no swapping necessary + case 2: + for (size_t i = 0; i < numReads; ++i) + ed_swap_2p(&data[i]); + break; + case 4: + for (size_t i = 0; i < numReads; ++i) + ed_swap_4p(&data[i]); + break; + case 8: + for (size_t i = 0; i < numReads; ++i) + ed_swap_8p(&data[i]); + break; + default: + throw std::runtime_error{"unsupported element size"}; + } +} + +template +inline void PbiIndexIO::WriteBgzfVector(BGZF* fp, const std::vector& data) +{ + assert(fp); + std::vector output = data; + if (fp->is_be) SwapEndianness(output); + auto ret = bgzf_write(fp, &output[0], data.size() * sizeof(T)); + UNUSED(ret); +} + +} // namespace BAM +} // namespace PacBio + +#endif // PBIINDEXIO_H diff --git a/src/PbiIndexedBamReader.cpp b/src/PbiIndexedBamReader.cpp new file mode 100644 index 0000000..7cc6ab2 --- /dev/null +++ b/src/PbiIndexedBamReader.cpp @@ -0,0 +1,183 @@ +// File Description +/// \file PbiIndexedBamReader.cpp +/// \brief Implements the PbiIndexedBamReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/PbiIndexedBamReader.h" + +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +class PbiIndexedBamReader::PbiIndexedBamReaderPrivate +{ +public: + explicit PbiIndexedBamReaderPrivate(BamFile file, const std::shared_ptr& index) + : file_{std::move(file)}, index_{index}, currentBlockReadCount_{0}, numMatchingReads_{0} + { + } + + void ApplyOffsets() + { + const auto& fileOffsets = index_->BasicData().fileOffset_; + for (IndexResultBlock& block : blocks_) + block.virtualOffset_ = fileOffsets.at(block.firstIndex_); + } + + void Filter(const PbiFilter filter) + { + // store request & reset counters + filter_ = std::move(filter); + currentBlockReadCount_ = 0; + blocks_.clear(); + numMatchingReads_ = 0; + + // find blocks of reads passing filter criteria + const auto totalReads = index_->NumReads(); + if (totalReads == 0) { // empty PBI - no reads to use + return; + } else if (filter_.IsEmpty()) { // empty filter - use all reads + numMatchingReads_ = totalReads; + blocks_.emplace_back(0, totalReads); + } else { + IndexList indices; + indices.reserve(totalReads); + const auto& idx = *index_; + for (size_t i = 0; i < totalReads; ++i) { + if (filter_.Accepts(idx, i)) { + indices.push_back(i); + ++numMatchingReads_; + } + } + blocks_ = MergedIndexBlocks(std::move(indices)); + } + + // apply offsets + ApplyOffsets(); + } + + IndexResultBlocks MergedIndexBlocks(IndexList indices) const + { + if (indices.empty()) return {}; + + std::sort(indices.begin(), indices.end()); + auto newEndIter = std::unique(indices.begin(), indices.end()); + auto numIndices = std::distance(indices.begin(), newEndIter); + auto result = IndexResultBlocks{IndexResultBlock{indices.at(0), 1}}; + for (auto i = 1; i < numIndices; ++i) { + if (indices.at(i) == indices.at(i - 1) + 1) + ++result.back().numReads_; + else + result.emplace_back(indices.at(i), 1); + } + return result; + } + + int ReadRawData(BGZF* bgzf, bam1_t* b) + { + // no data to fetch, return false + if (blocks_.empty()) return -1; // "EOF" + + // if on new block, seek to its first record + if (currentBlockReadCount_ == 0) { + const auto seekResult = bgzf_seek(bgzf, blocks_.at(0).virtualOffset_, SEEK_SET); + if (seekResult == -1) + throw std::runtime_error{"PbiIndexedBamReader: could not seek in BAM file"}; + } + + // read next record + const auto result = bam_read1(bgzf, b); + + // update counters. if block finished, pop & reset + ++currentBlockReadCount_; + if (currentBlockReadCount_ == blocks_.at(0).numReads_) { + blocks_.pop_front(); + currentBlockReadCount_ = 0; + } + + return result; + } + + BamFile file_; + PbiFilter filter_; + std::shared_ptr index_; + IndexResultBlocks blocks_; + size_t currentBlockReadCount_; + uint32_t numMatchingReads_; +}; + +PbiIndexedBamReader::PbiIndexedBamReader(PbiFilter filter, const std::string& filename) + : PbiIndexedBamReader{std::move(filter), BamFile{filename}} +{ +} + +PbiIndexedBamReader::PbiIndexedBamReader(PbiFilter filter, const std::string& filename, + const std::shared_ptr& index) + : PbiIndexedBamReader{std::move(filter), BamFile{filename}, index} +{ +} + +PbiIndexedBamReader::PbiIndexedBamReader(PbiFilter filter, BamFile bamFile) + : PbiIndexedBamReader{std::move(bamFile)} +{ + Filter(std::move(filter)); +} + +PbiIndexedBamReader::PbiIndexedBamReader(PbiFilter filter, BamFile bamFile, + const std::shared_ptr& index) + : PbiIndexedBamReader{std::move(bamFile), index} +{ + Filter(std::move(filter)); +} + +PbiIndexedBamReader::PbiIndexedBamReader(const std::string& bamFilename) + : PbiIndexedBamReader{BamFile{bamFilename}} +{ +} + +PbiIndexedBamReader::PbiIndexedBamReader(const std::string& bamFilename, + const std::shared_ptr& index) + : PbiIndexedBamReader{BamFile{bamFilename}, index} +{ +} + +PbiIndexedBamReader::PbiIndexedBamReader(BamFile bamFile) : BamReader{bamFile.Filename()} +{ + auto indexCache = MakePbiIndexCache(bamFile); + d_ = std::make_unique(std::move(bamFile), indexCache->at(0)); +} + +PbiIndexedBamReader::PbiIndexedBamReader(BamFile bamFile, const std::shared_ptr& index) + : BamReader{bamFile.Filename()} + , d_{std::make_unique(std::move(bamFile), index)} +{ +} + +PbiIndexedBamReader::~PbiIndexedBamReader() = default; + +const BamFile& PbiIndexedBamReader::File() const { return d_->file_; } + +const PbiFilter& PbiIndexedBamReader::Filter() const { return d_->filter_; } + +PbiIndexedBamReader& PbiIndexedBamReader::Filter(PbiFilter filter) +{ + d_->Filter(std::move(filter)); + return *this; +} + +const IndexResultBlocks& PbiIndexedBamReader::IndexBlocks() const { return d_->blocks_; } + +uint32_t PbiIndexedBamReader::NumReads() const { return d_->numMatchingReads_; } + +int PbiIndexedBamReader::ReadRawData(BGZF* bgzf, bam1_t* b) { return d_->ReadRawData(bgzf, b); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/PbiRawData.cpp b/src/PbiRawData.cpp new file mode 100644 index 0000000..381bb51 --- /dev/null +++ b/src/PbiRawData.cpp @@ -0,0 +1,352 @@ +// File Description +/// \file PbiRawData.cpp +/// \brief Implements the classes used for working with raw PBI data. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/PbiRawData.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "PbiIndexIO.h" +#include "pbbam/BamFile.h" +#include "pbbam/BamRecord.h" +#include "pbbam/RecordType.h" + +namespace PacBio { +namespace BAM { + +// ---------------------------------- +// PbiRawBarcodeData implementation +// ---------------------------------- + +static_assert(std::is_copy_constructible::value, + "PbiRawBarcodeData(const PbiRawBarcodeData&) is not = default"); +static_assert(std::is_copy_assignable::value, + "PbiRawBarcodeData& operator=(const PbiRawBarcodeData&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "PbiRawBarcodeData(PbiRawBarcodeData&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "PbiRawBarcodeData& operator=(PbiRawBarcodeData&&) is not = noexcept"); + +PbiRawBarcodeData::PbiRawBarcodeData(uint32_t numReads) +{ + bcForward_.reserve(numReads); + bcReverse_.reserve(numReads); + bcQual_.reserve(numReads); +} + +void PbiRawBarcodeData::AddRecord(const BamRecord& b) +{ + // check for any barcode data (both required) + if (b.HasBarcodes() && b.HasBarcodeQuality()) { + + // fetch data from record + int16_t bcForward; + int16_t bcReverse; + std::tie(bcForward, bcReverse) = b.Barcodes(); + + const auto bcQuality = boost::numeric_cast(b.BarcodeQuality()); + + // only store actual data if all values >= 0 + if (bcForward >= 0 && bcReverse >= 0 && bcQuality >= 0) { + bcForward_.push_back(bcForward); + bcReverse_.push_back(bcReverse); + bcQual_.push_back(bcQuality); + return; + } + } + + // if we get here, at least one value is either missing or is -1 + bcForward_.push_back(-1); + bcReverse_.push_back(-1); + bcQual_.push_back(-1); +} + +// ---------------------------------- +// PbiRawMappedData implementation +// ---------------------------------- + +static_assert(std::is_copy_constructible::value, + "PbiRawMappedData(const PbiRawMappedData&) is not = default"); +static_assert(std::is_copy_assignable::value, + "PbiRawMappedData& operator=(const PbiRawMappedData&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "PbiRawMappedData(PbiRawMappedData&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "PbiRawMappedData& operator=(PbiRawMappedData&&) is not = noexcept"); + +PbiRawMappedData::PbiRawMappedData(uint32_t numReads) +{ + tId_.reserve(numReads); + tStart_.reserve(numReads); + tEnd_.reserve(numReads); + aStart_.reserve(numReads); + aEnd_.reserve(numReads); + revStrand_.reserve(numReads); + nM_.reserve(numReads); + nMM_.reserve(numReads); + mapQV_.reserve(numReads); +} + +void PbiRawMappedData::AddRecord(const BamRecord& b) +{ + tId_.push_back(b.ReferenceId()); + tStart_.push_back(b.ReferenceStart()); + tEnd_.push_back(b.ReferenceEnd()); + aStart_.push_back(b.AlignedStart()); + aEnd_.push_back(b.AlignedEnd()); + revStrand_.push_back((b.AlignedStrand() == Strand::REVERSE ? 1 : 0)); + mapQV_.push_back(b.MapQuality()); + + const auto matchesAndMismatches = b.NumMatchesAndMismatches(); + nM_.push_back(matchesAndMismatches.first); + nMM_.push_back(matchesAndMismatches.second); +} + +uint32_t PbiRawMappedData::NumDeletedBasesAt(size_t recordIndex) const +{ + return NumDeletedAndInsertedBasesAt(recordIndex).first; +} + +std::pair PbiRawMappedData::NumDeletedAndInsertedBasesAt( + size_t recordIndex) const +{ + const auto aStart = aStart_.at(recordIndex); + const auto aEnd = aEnd_.at(recordIndex); + const auto tStart = tStart_.at(recordIndex); + const auto tEnd = tEnd_.at(recordIndex); + const auto nM = nM_.at(recordIndex); + const auto nMM = nMM_.at(recordIndex); + + const auto numIns = (aEnd - aStart - nM - nMM); + const auto numDel = (tEnd - tStart - nM - nMM); + return {numDel, numIns}; +} + +uint32_t PbiRawMappedData::NumInsertedBasesAt(size_t recordIndex) const +{ + return NumDeletedAndInsertedBasesAt(recordIndex).second; +} + +// ------------------------------------ +// PbiReferenceEntry implementation +// ------------------------------------ + +static_assert(std::is_copy_constructible::value, + "PbiReferenceEntry(const PbiReferenceEntry&) is not = default"); +static_assert(std::is_copy_assignable::value, + "PbiReferenceEntry& operator=(const PbiReferenceEntry&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "PbiReferenceEntry(PbiReferenceEntry&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "PbiReferenceEntry& operator=(PbiReferenceEntry&&) is not = noexcept"); + +const PbiReferenceEntry::ID PbiReferenceEntry::UNMAPPED_ID = static_cast(-1); +const PbiReferenceEntry::Row PbiReferenceEntry::UNSET_ROW = static_cast(-1); + +PbiReferenceEntry::PbiReferenceEntry() : PbiReferenceEntry{UNMAPPED_ID, UNSET_ROW, UNSET_ROW} {} + +PbiReferenceEntry::PbiReferenceEntry(ID id) : PbiReferenceEntry{id, UNSET_ROW, UNSET_ROW} {} + +PbiReferenceEntry::PbiReferenceEntry(ID id, Row beginRow, Row endRow) + : tId_{id}, beginRow_{beginRow}, endRow_{endRow} +{ +} + +// ------------------------------------ +// PbiRawReferenceData implementation +// ------------------------------------ + +static_assert(std::is_copy_constructible::value, + "PbiRawReferenceData(const PbiRawReferenceData&) is not = default"); +static_assert(std::is_copy_assignable::value, + "PbiRawReferenceData& operator=(const PbiRawReferenceData&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "PbiRawReferenceData(PbiRawReferenceData&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "PbiRawReferenceData& operator=(PbiRawReferenceData&&) is not = noexcept"); + +PbiRawReferenceData::PbiRawReferenceData(uint32_t numRefs) { entries_.reserve(numRefs); } + +// ---------------------------------- +// PbiRawBasicData implementation +// ---------------------------------- + +static_assert(std::is_copy_constructible::value, + "PbiRawBasicData(const PbiRawBasicData&) is not = default"); +static_assert(std::is_copy_assignable::value, + "PbiRawBasicData& operator=(const PbiRawBasicData&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "PbiRawBasicData(PbiRawBasicData&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "PbiRawBasicData& operator=(PbiRawBasicData&&) is not = noexcept"); + +PbiRawBasicData::PbiRawBasicData(uint32_t numReads) +{ + rgId_.reserve(numReads); + qStart_.reserve(numReads); + qEnd_.reserve(numReads); + holeNumber_.reserve(numReads); + readQual_.reserve(numReads); + ctxtFlag_.reserve(numReads); + fileOffset_.reserve(numReads); + fileNumber_.reserve(numReads); +} + +void PbiRawBasicData::AddRecord(const BamRecord& b, int64_t offset) +{ + // read group ID + auto rgId = b.ReadGroupBaseId(); + if (rgId.empty()) rgId = MakeReadGroupId(b.MovieName(), ToString(b.Type())); + const auto rawid = std::stoul(rgId, nullptr, 16); + const auto id = static_cast(rawid); + rgId_.push_back(id); + + // query start/end + if (IsCcsOrTranscript(b.Type())) { + qStart_.push_back(0); + qEnd_.push_back(b.Impl().SequenceLength()); + } else { + qStart_.push_back(b.QueryStart()); + qEnd_.push_back(b.QueryEnd()); + } + + // add'l basic data + holeNumber_.push_back(b.HasHoleNumber() ? b.HoleNumber() : 0); + readQual_.push_back(b.HasReadAccuracy() ? static_cast(b.ReadAccuracy()) : 0.0f); + ctxtFlag_.push_back(b.HasLocalContextFlags() ? b.LocalContextFlags() + : LocalContextFlags::NO_LOCAL_CONTEXT); + + // virtual offset of record start + fileOffset_.push_back(offset); + + // default file number + fileNumber_.push_back(0); +} + +// ---------------------------------- +// PbiRawData implementation +// ---------------------------------- + +static_assert(std::is_copy_constructible::value, + "PbiRawData(const PbiRawData&) is not = default"); +static_assert(std::is_copy_assignable::value, + "PbiRawData& operator=(const PbiRawData&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "PbiRawData(PbiRawData&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +PbiRawData::PbiRawData(std::string pbiFilename) : filename_{std::move(pbiFilename)} +{ + PbiIndexIO::Load(*this, filename_); +} + +PbiRawData::PbiRawData(const DataSet& dataset) + : sections_{PbiFile::BASIC | PbiFile::MAPPED | PbiFile::BARCODE} +{ + PbiIndexIO::LoadFromDataSet(*this, dataset); +} + +const PbiRawBarcodeData& PbiRawData::BarcodeData() const { return barcodeData_; } + +PbiRawBarcodeData& PbiRawData::BarcodeData() { return barcodeData_; } + +const PbiRawBasicData& PbiRawData::BasicData() const { return basicData_; } + +PbiRawBasicData& PbiRawData::BasicData() { return basicData_; } + +std::string PbiRawData::Filename() const { return filename_; } + +PbiFile::Sections PbiRawData::FileSections() const { return sections_; } + +PbiRawData& PbiRawData::FileSections(PbiFile::Sections sections) +{ + sections_ = sections; + return *this; +} + +bool PbiRawData::HasBarcodeData() const { return HasSection(PbiFile::BARCODE); } + +bool PbiRawData::HasMappedData() const { return HasSection(PbiFile::MAPPED); } + +bool PbiRawData::HasReferenceData() const { return HasSection(PbiFile::REFERENCE); } + +bool PbiRawData::HasSection(const PbiFile::Section section) const +{ + return (sections_ & section) != 0; +} + +uint32_t PbiRawData::NumReads() const { return numReads_; } + +PbiRawData& PbiRawData::NumReads(uint32_t num) +{ + numReads_ = num; + return *this; +} + +const PbiRawMappedData& PbiRawData::MappedData() const { return mappedData_; } + +PbiRawMappedData& PbiRawData::MappedData() { return mappedData_; } + +const PbiRawReferenceData& PbiRawData::ReferenceData() const { return referenceData_; } + +PbiRawReferenceData& PbiRawData::ReferenceData() { return referenceData_; } + +PbiFile::VersionEnum PbiRawData::Version() const { return version_; } + +PbiRawData& PbiRawData::Version(PbiFile::VersionEnum version) +{ + version_ = version; + return *this; +} + +bool PbiReferenceEntry::operator==(const PbiReferenceEntry& other) const +{ + return std::tie(tId_, beginRow_, endRow_) == + std::tie(other.tId_, other.beginRow_, other.endRow_); +} + +// PBI index caching + +PbiIndexCache MakePbiIndexCache(const DataSet& dataset) +{ + return MakePbiIndexCache(dataset.BamFiles()); +} + +PbiIndexCache MakePbiIndexCache(const std::vector& bamFiles) +{ + PbiIndexCache cache = std::make_shared>>(); + auto& indices = *cache.get(); + for (const auto& bamFile : bamFiles) { + const auto& pbiFilename = bamFile.PacBioIndexFilename(); + indices.push_back(std::make_shared(pbiFilename)); + } + return cache; +} + +PbiIndexCache MakePbiIndexCache(const BamFile& bamFile) +{ + std::vector bamFiles{bamFile}; + return MakePbiIndexCache(bamFiles); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/ProgramInfo.cpp b/src/ProgramInfo.cpp new file mode 100644 index 0000000..74700b2 --- /dev/null +++ b/src/ProgramInfo.cpp @@ -0,0 +1,157 @@ +// File Description +/// \file ProgramInfo.cpp +/// \brief Implements the ProgramInfo class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ProgramInfo.h" + +#include +#include +#include + +#include "pbbam/SamTagCodec.h" +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { +namespace { + +const std::string ProgramInfoTokenID{"ID"}; +const std::string ProgramInfoTokenCL{"CL"}; +const std::string ProgramInfoTokenDS{"DS"}; +const std::string ProgramInfoTokenPN{"PN"}; +const std::string ProgramInfoTokenPP{"PP"}; +const std::string ProgramInfoTokenVN{"VN"}; + +} // anonymous + +static_assert(std::is_copy_constructible::value, + "ProgramInfo(const ProgramInfo&) is not = default"); +static_assert(std::is_copy_assignable::value, + "ProgramInfo& operator=(const ProgramInfo&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "ProgramInfo(ProgramInfo&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +ProgramInfo::ProgramInfo(std::string id) : id_{std::move(id)} {} + +std::string ProgramInfo::CommandLine() const { return commandLine_; } + +ProgramInfo& ProgramInfo::CommandLine(std::string cmd) +{ + commandLine_ = std::move(cmd); + return *this; +} + +std::map ProgramInfo::CustomTags() const { return custom_; } + +ProgramInfo& ProgramInfo::CustomTags(std::map custom) +{ + custom_ = std::move(custom); + return *this; +} + +std::string ProgramInfo::Description() const { return description_; } + +ProgramInfo& ProgramInfo::Description(std::string description) +{ + description_ = std::move(description); + return *this; +} + +ProgramInfo ProgramInfo::FromSam(const std::string& sam) +{ + // pop off '@PG\t', then split rest of line into tokens + const auto tokens = Split(sam.substr(4), '\t'); + if (tokens.empty()) return {}; + + ProgramInfo prog; + std::map custom; + + // iterate over tokens + for (const auto& token : tokens) { + const auto tokenTag = token.substr(0, 2); + auto tokenValue = token.substr(3); + + // set program contents + // clang-format off + if (tokenTag == ProgramInfoTokenID) prog.Id(std::move(tokenValue)); + else if (tokenTag == ProgramInfoTokenCL) prog.CommandLine(std::move(tokenValue)); + else if (tokenTag == ProgramInfoTokenDS) prog.Description(std::move(tokenValue)); + else if (tokenTag == ProgramInfoTokenPN) prog.Name(std::move(tokenValue)); + else if (tokenTag == ProgramInfoTokenPP) prog.PreviousProgramId(std::move(tokenValue)); + else if (tokenTag == ProgramInfoTokenVN) prog.Version(std::move(tokenValue)); + // clang-format on + + // otherwise, "custom" tag + else + custom[tokenTag] = std::move(tokenValue); + } + + prog.CustomTags(custom); + return prog; +} + +std::string ProgramInfo::Id() const { return id_; } + +ProgramInfo& ProgramInfo::Id(std::string id) +{ + id_ = std::move(id); + return *this; +} + +bool ProgramInfo::IsValid() const { return !id_.empty(); } + +std::string ProgramInfo::Name() const { return name_; } + +ProgramInfo& ProgramInfo::Name(std::string name) +{ + name_ = std::move(name); + return *this; +} + +std::string ProgramInfo::PreviousProgramId() const { return previousProgramId_; } + +ProgramInfo& ProgramInfo::PreviousProgramId(std::string id) +{ + previousProgramId_ = std::move(id); + return *this; +} + +std::string ProgramInfo::ToSam(const ProgramInfo& prog) { return prog.ToSam(); } + +std::string ProgramInfo::ToSam() const +{ + std::ostringstream out; + out << "@PG" << MakeSamTag(ProgramInfoTokenID, id_); + + // clang-format off + if (!name_.empty()) out << MakeSamTag(ProgramInfoTokenPN, name_); + if (!version_.empty()) out << MakeSamTag(ProgramInfoTokenVN, version_); + if (!description_.empty()) out << MakeSamTag(ProgramInfoTokenDS, description_); + if (!previousProgramId_.empty()) out << MakeSamTag(ProgramInfoTokenPP, previousProgramId_); + if (!commandLine_.empty()) out << MakeSamTag(ProgramInfoTokenCL, commandLine_); + // clang-format on + + // append any custom tags + for (const auto& attribute : custom_) + out << MakeSamTag(attribute.first, attribute.second); + return out.str(); +} + +std::string ProgramInfo::Version() const { return version_; } + +ProgramInfo& ProgramInfo::Version(std::string version) +{ + version_ = std::move(version); + return *this; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/Pulse2BaseCache.h b/src/Pulse2BaseCache.h new file mode 100644 index 0000000..3b60825 --- /dev/null +++ b/src/Pulse2BaseCache.h @@ -0,0 +1,117 @@ +// Author: Derek Barnett + +#ifndef PULSE2BASECACHE_H +#define PULSE2BASECACHE_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { + +class Pulse2BaseCache +{ +public: + /// \brief Creates a Pulse2BaseCache from pulseCall data ('pc' tag) + /// + /// Computes & stores cache of basecalled vs. squashed pulse positions for + /// later masking of pulse data. + /// + /// \param pulseCalls[in] string contents of 'pc' tag + /// + explicit Pulse2BaseCache(const std::string& pulseCalls) : data_(pulseCalls.size()) + { + // basecalled pulse -> data[i] == 1 + // squashed pulse -> data[i] == 0 + // + const auto numPulses = pulseCalls.size(); + for (size_t i = 0; i < numPulses; ++i) + data_[i] = std::isupper(pulseCalls.at(i)); + } + + Pulse2BaseCache() = delete; + Pulse2BaseCache(const Pulse2BaseCache&) = default; + Pulse2BaseCache(Pulse2BaseCache&&) noexcept( + std::is_nothrow_move_constructible>::value); + Pulse2BaseCache& operator=(const Pulse2BaseCache&) = default; + Pulse2BaseCache& operator=(Pulse2BaseCache&&) noexcept( + std::is_nothrow_move_assignable>::value); + ~Pulse2BaseCache() = default; + + /// + /// \brief FindFirst + /// \return + /// + size_t FindFirst() const { return data_.find_first(); } + + /// + /// \brief FindNext + /// \param from + /// \return + /// + size_t FindNext(size_t from) const { return data_.find_next(from); } + + /// + /// \brief IsBasecallAt + /// \param pos + /// \return + /// + bool IsBasecallAt(const size_t pos) const { return data_[pos]; } + + /// \returns the total number of pulses (basecalled & squashed) + /// + size_t NumPulses() const { return data_.size(); } + + /// \returns the total number of basecalled pulses + /// + size_t NumBases() const { return data_.count(); } + + /// \brief Removes squashed pulse positions from input data. + /// + /// \param[in] Contents of any per-pulse tag. + /// \returns Input \p pulseData less all squashed pulses + /// + template + T RemoveSquashedPulses(const T& pulseData) const + { + const auto numPulses = pulseData.size(); + assert(numPulses == data_.size()); + + // The reserve() below overshoots the required space, but numPulses is cheap + // to compute, and by definition will be sufficient to hold the result. Thus + // we only ever need to do one allocation. + // + T result; + result.reserve(numPulses); + + // Only include data at positions that match our cached pulse data. + // + size_t inputIndex = 0; + for (size_t i = 0; i < numPulses; ++i) { + if (data_[i]) result.push_back(pulseData.at(inputIndex)); + ++inputIndex; + } + return result; + } + +private: + boost::dynamic_bitset<> data_; +}; + +inline Pulse2BaseCache::Pulse2BaseCache(Pulse2BaseCache&&) noexcept( + std::is_nothrow_move_constructible>::value) = default; + +inline Pulse2BaseCache& Pulse2BaseCache::operator=(Pulse2BaseCache&&) noexcept( + std::is_nothrow_move_assignable>::value) = default; + +} // namespace BAM +} // namespace PacBio + +#endif // PULSE2BASECACHE_H diff --git a/src/QNameQuery.cpp b/src/QNameQuery.cpp new file mode 100644 index 0000000..493e215 --- /dev/null +++ b/src/QNameQuery.cpp @@ -0,0 +1,74 @@ +// File Description +/// \file QNameQuery.cpp +/// \brief Implements the QNameQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/QNameQuery.h" + +#include + +#include + +#include "pbbam/CompositeBamReader.h" + +namespace PacBio { +namespace BAM { + +class QNameQuery::QNameQueryPrivate +{ +public: + QNameQueryPrivate(const DataSet& dataset) + : reader_{std::make_unique(dataset)}, nextRecord_(boost::none) + { + } + + bool GetNext(std::vector& records) + { + records.clear(); + + std::string groupRecordName; + + if (nextRecord_.is_initialized()) { + BamRecord r = nextRecord_.get(); + groupRecordName = r.FullName(); + records.push_back(std::move(r)); + nextRecord_ = boost::none; + } + + BamRecord record; + while (reader_->GetNext(record)) { + if (records.empty()) { + groupRecordName = record.FullName(); + records.push_back(record); + } else { + assert(!records.empty()); + if (record.FullName() == groupRecordName) + records.push_back(record); + else { + nextRecord_ = record; + return true; + } + } + } + return !records.empty(); + } + +private: + std::unique_ptr reader_; + boost::optional nextRecord_; +}; + +QNameQuery::QNameQuery(const DataSet& dataset) + : internal::IGroupQuery(), d_{std::make_unique(dataset)} +{ +} + +QNameQuery::~QNameQuery() = default; + +bool QNameQuery::GetNext(std::vector& records) { return d_->GetNext(records); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ReadAccuracyQuery.cpp b/src/ReadAccuracyQuery.cpp new file mode 100644 index 0000000..f258529 --- /dev/null +++ b/src/ReadAccuracyQuery.cpp @@ -0,0 +1,43 @@ +// File Description +/// \file ReadAccuracyQuery.cpp +/// \brief Implements the ReadAccuracyQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ReadAccuracyQuery.h" + +#include "pbbam/CompositeBamReader.h" +#include "pbbam/PbiFilterTypes.h" + +namespace PacBio { +namespace BAM { + +class ReadAccuracyQuery::ReadAccuracyQueryPrivate +{ +public: + ReadAccuracyQueryPrivate(const Accuracy accuracy, const Compare::Type compareType, + const DataSet& dataset) + : reader_{PbiReadAccuracyFilter{accuracy, compareType}, dataset} + { + } + + PbiFilterCompositeBamReader reader_; // unsorted +}; + +ReadAccuracyQuery::ReadAccuracyQuery(const Accuracy accuracy, const Compare::Type compareType, + const DataSet& dataset) + : internal::IQuery() + , d_{std::make_unique(accuracy, compareType, dataset)} +{ +} + +ReadAccuracyQuery::~ReadAccuracyQuery() = default; + +bool ReadAccuracyQuery::GetNext(BamRecord& r) { return d_->reader_.GetNext(r); } + +uint32_t ReadAccuracyQuery::NumReads() const { return d_->reader_.NumReads(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ReadGroupInfo.cpp b/src/ReadGroupInfo.cpp new file mode 100644 index 0000000..791b5e1 --- /dev/null +++ b/src/ReadGroupInfo.cpp @@ -0,0 +1,920 @@ +// File Description +/// \file ReadGroupInfo.cpp +/// \brief Implements the ReadGroupInfo class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ReadGroupInfo.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ChemistryTable.h" +#include "pbbam/MD5.h" +#include "pbbam/SamTagCodec.h" +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { +namespace { + +static const std::string sam_ID{"ID"}; +static const std::string sam_CN{"CN"}; +static const std::string sam_DS{"DS"}; +static const std::string sam_DT{"DT"}; +static const std::string sam_FO{"FO"}; +static const std::string sam_KS{"KS"}; +static const std::string sam_LB{"LB"}; +static const std::string sam_PG{"PG"}; +static const std::string sam_PI{"PI"}; +static const std::string sam_PL{"PL"}; +static const std::string sam_PM{"PM"}; +static const std::string sam_PU{"PU"}; +static const std::string sam_SM{"SM"}; +static const std::string sam_BC{"BC"}; + +static const std::string feature_DQ{"DeletionQV"}; +static const std::string feature_DT{"DeletionTag"}; +static const std::string feature_IQ{"InsertionQV"}; +static const std::string feature_MQ{"MergeQV"}; +static const std::string feature_SQ{"SubstitutionQV"}; +static const std::string feature_ST{"SubstitutionTag"}; +static const std::string feature_IP{"Ipd"}; +static const std::string feature_PW{"PulseWidth"}; +static const std::string feature_PM{"PkMid"}; +static const std::string feature_PA{"PkMean"}; +static const std::string feature_PI{"PkMid2"}; +static const std::string feature_PS{"PkMean2"}; +static const std::string feature_LT{"Label"}; +static const std::string feature_PQ{"LabelQV"}; +static const std::string feature_PT{"AltLabel"}; +static const std::string feature_PV{"AltLabelQV"}; +static const std::string feature_PG{"PulseMergeQV"}; +static const std::string feature_PC{"PulseCall"}; +static const std::string feature_PD{"PrePulseFrames"}; +static const std::string feature_PX{"PulseCallWidth"}; +static const std::string feature_SF{"StartFrame"}; +static const std::string feature_PE{"PulseExclusion"}; + +static const std::string token_RT{"READTYPE"}; +static const std::string token_BK{"BINDINGKIT"}; +static const std::string token_SK{"SEQUENCINGKIT"}; +static const std::string token_BV{"BASECALLERVERSION"}; +static const std::string token_FR{"FRAMERATEHZ"}; +static const std::string token_CT{"CONTROL"}; + +static const std::string token_BF{"BarcodeFile"}; +static const std::string token_BH{"BarcodeHash"}; +static const std::string token_BC{"BarcodeCount"}; +static const std::string token_BM{"BarcodeMode"}; +static const std::string token_BQ{"BarcodeQuality"}; + +static const std::string codec_RAW{"Frames"}; +static const std::string codec_V1{"CodecV1"}; + +static const std::string barcodemode_NONE{"None"}; +static const std::string barcodemode_SYM{"Symmetric"}; +static const std::string barcodemode_ASYM{"Asymmetric"}; +static const std::string barcodemode_TAIL{"Tailed"}; + +static const std::string barcodequal_NONE{"None"}; +static const std::string barcodequal_SCORE{"Score"}; +static const std::string barcodequal_PROB{"Probability"}; + +static const std::string platformModelType_ASTRO{"ASTRO"}; +static const std::string platformModelType_RS{"RS"}; +static const std::string platformModelType_SEQUEL{"SEQUEL"}; +static const std::string platformModelType_SEQUELII{"SEQUELII"}; + +// clang-format off +std::string BaseFeatureName(const BaseFeature& feature) +{ + static const std::unordered_map lookup{ + {BaseFeature::DELETION_QV, feature_DQ}, + {BaseFeature::DELETION_TAG, feature_DT}, + {BaseFeature::INSERTION_QV, feature_IQ}, + {BaseFeature::MERGE_QV, feature_MQ}, + {BaseFeature::SUBSTITUTION_QV, feature_SQ}, + {BaseFeature::SUBSTITUTION_TAG, feature_ST}, + {BaseFeature::IPD, feature_IP}, + {BaseFeature::PULSE_WIDTH, feature_PW}, + {BaseFeature::PKMID, feature_PM}, + {BaseFeature::PKMEAN, feature_PA}, + {BaseFeature::PKMID2, feature_PI}, + {BaseFeature::PKMEAN2, feature_PS}, + {BaseFeature::LABEL_QV, feature_PQ}, + {BaseFeature::ALT_LABEL, feature_PT}, + {BaseFeature::ALT_LABEL_QV, feature_PV}, + {BaseFeature::PULSE_MERGE_QV, feature_PG}, + {BaseFeature::PULSE_CALL, feature_PC}, + {BaseFeature::PRE_PULSE_FRAMES, feature_PD}, + {BaseFeature::PULSE_CALL_WIDTH, feature_PX}, + {BaseFeature::START_FRAME, feature_SF}, + {BaseFeature::PULSE_EXCLUSION, feature_PE} + }; + + const auto found = lookup.find(feature); + if (found != lookup.cend()) + return found->second; + throw std::runtime_error{ "ReadGroupInfo: unrecognized base feature" }; +} + +std::string FrameCodecName(const FrameCodec& codec) +{ + static const std::unordered_map lookup{ + {FrameCodec::RAW, codec_RAW}, + {FrameCodec::V1, codec_V1} + }; + + const auto found = lookup.find(codec); + if (found != lookup.cend()) + return found->second; + throw std::runtime_error{ "ReadGroupInfo: unrecognized frame codec" }; +} + +std::string BarcodeModeName(const BarcodeModeType& mode) +{ + static const std::unordered_map lookup{ + {BarcodeModeType::NONE, barcodemode_NONE}, + {BarcodeModeType::SYMMETRIC, barcodemode_SYM}, + {BarcodeModeType::ASYMMETRIC, barcodemode_ASYM}, + {BarcodeModeType::TAILED, barcodemode_TAIL} + }; + + const auto found = lookup.find(mode); + if (found != lookup.cend()) + return found->second; + throw std::runtime_error{ "ReadGroupInfo: unrecognized barcode mode type" }; +} + +std::string BarcodeQualityName(const BarcodeQualityType& type) +{ + static const std::unordered_map lookup{ + {BarcodeQualityType::NONE, barcodequal_NONE}, + {BarcodeQualityType::SCORE, barcodequal_SCORE}, + {BarcodeQualityType::PROBABILITY, barcodequal_PROB} + }; + + const auto found = lookup.find(type); + if (found != lookup.cend()) + return found->second; + throw std::runtime_error{ "ReadGroupInfo: unrecognized barcode quality type" }; +} + +std::string PlatformModelName(const PlatformModelType& type) +{ + static const std::unordered_map lookup{ + {PlatformModelType::ASTRO, platformModelType_ASTRO}, + {PlatformModelType::RS, platformModelType_RS}, + {PlatformModelType::SEQUEL, platformModelType_SEQUEL}, + {PlatformModelType::SEQUELII, platformModelType_SEQUELII} + }; + + const auto found = lookup.find(type); + if (found != lookup.cend()) + return found->second; + throw std::runtime_error{ "ReadGroupInfo: unrecognized platform model type" }; +} + +static const std::map nameToFeature +{ + { feature_DQ, BaseFeature::DELETION_QV }, + { feature_DT, BaseFeature::DELETION_TAG }, + { feature_IQ, BaseFeature::INSERTION_QV }, + { feature_MQ, BaseFeature::MERGE_QV }, + { feature_SQ, BaseFeature::SUBSTITUTION_QV }, + { feature_ST, BaseFeature::SUBSTITUTION_TAG }, + { feature_IP, BaseFeature::IPD }, + { feature_PW, BaseFeature::PULSE_WIDTH }, + { feature_PM, BaseFeature::PKMID }, + { feature_PA, BaseFeature::PKMEAN }, + { feature_PI, BaseFeature::PKMID2 }, + { feature_PS, BaseFeature::PKMEAN2 }, + { feature_PQ, BaseFeature::LABEL_QV }, + { feature_PT, BaseFeature::ALT_LABEL }, + { feature_PV, BaseFeature::ALT_LABEL_QV }, + { feature_PC, BaseFeature::PULSE_CALL }, + { feature_PG, BaseFeature::PULSE_MERGE_QV }, + { feature_PD, BaseFeature::PRE_PULSE_FRAMES }, + { feature_PX, BaseFeature::PULSE_CALL_WIDTH }, + { feature_SF, BaseFeature::START_FRAME }, + { feature_PE, BaseFeature::PULSE_EXCLUSION } +}; + +static const std::map nameToCodec +{ + { codec_RAW, FrameCodec::RAW }, + { codec_V1, FrameCodec::V1 } +}; + +static const std::map nameToBarcodeMode +{ + { barcodemode_NONE, BarcodeModeType::NONE }, + { barcodemode_SYM, BarcodeModeType::SYMMETRIC }, + { barcodemode_ASYM, BarcodeModeType::ASYMMETRIC }, + { barcodemode_TAIL, BarcodeModeType::TAILED } +}; + +static const std::map nameToBarcodeQuality +{ + { barcodequal_NONE, BarcodeQualityType::NONE }, + { barcodequal_SCORE, BarcodeQualityType::SCORE }, + { barcodequal_PROB, BarcodeQualityType::PROBABILITY } +}; + +static const std::map nameToPlatformModel +{ + { platformModelType_ASTRO, PlatformModelType::ASTRO }, + { platformModelType_RS, PlatformModelType::RS }, + { platformModelType_SEQUEL, PlatformModelType::SEQUEL }, + { platformModelType_SEQUELII, PlatformModelType::SEQUELII } +}; +// clang-format on + +bool IsLikelyBarcodeKey(const std::string& name) { return name.find("Barcode") == 0; } + +bool IsBaseFeature(const std::string& name) +{ + return nameToFeature.find(name) != nameToFeature.cend(); +} + +BaseFeature BaseFeatureFromName(const std::string& name) { return nameToFeature.at(name); } + +FrameCodec FrameCodecFromName(const std::string& name) { return nameToCodec.at(name); } + +BarcodeModeType BarcodeModeFromName(const std::string& name) { return nameToBarcodeMode.at(name); } + +BarcodeQualityType BarcodeQualityFromName(const std::string& name) +{ + return nameToBarcodeQuality.at(name); +} + +PlatformModelType PlatformModelFromName(std::string name) { return nameToPlatformModel.at(name); } + +} // namespace + +static_assert(std::is_copy_constructible::value, + "ReadGroupInfo(const ReadGroupInfo&) is not = default"); +static_assert(std::is_copy_assignable::value, + "ReadGroupInfo& operator=(const ReadGroupInfo&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "ReadGroupInfo(ReadGroupInfo&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +ReadGroupInfo::ReadGroupInfo(std::string baseId, std::pair barcodes) + +{ + std::ostringstream id; + id << baseId << '/' << std::to_string(barcodes.first) << "--" + << std::to_string(barcodes.second); + id_ = id.str(); + baseId_ = std::move(baseId); + barcodes_ = std::move(barcodes); +} + +ReadGroupInfo::ReadGroupInfo() : readType_{"UNKNOWN"} {} + +ReadGroupInfo::ReadGroupInfo(std::string id) : readType_{"UNKNOWN"} { Id(std::move(id)); } + +ReadGroupInfo::ReadGroupInfo(std::string movieName, std::string readType) + : ReadGroupInfo{std::move(movieName), std::move(readType), PlatformModelType::SEQUEL} +{ +} + +ReadGroupInfo::ReadGroupInfo(std::string movieName, std::string readType, + std::pair barcodes) + : ReadGroupInfo{std::move(movieName), std::move(readType), PlatformModelType::SEQUEL, + std::move(barcodes)} +{ +} + +ReadGroupInfo::ReadGroupInfo(std::string movieName, std::string readType, + PlatformModelType platform) + : platformModel_{std::move(platform)} +{ + Id(MakeReadGroupId(movieName, readType)); + movieName_ = std::move(movieName); + readType_ = std::move(readType); +} + +ReadGroupInfo::ReadGroupInfo(std::string movieName, std::string readType, + PlatformModelType platform, std::pair barcodes) + : ReadGroupInfo{MakeReadGroupId(movieName, readType), std::move(barcodes)} +{ + platformModel_ = std::move(platform); +} + +bool ReadGroupInfo::operator==(const ReadGroupInfo& other) const +{ + const auto lhsFields = std::tie( + id_, sequencingCenter_, date_, flowOrder_, keySequence_, library_, programs_, + platformModel_, predictedInsertSize_, movieName_, sample_, readType_, bindingKit_, + sequencingKit_, basecallerVersion_, frameRateHz_, control_, ipdCodec_, pulseWidthCodec_, + hasBarcodeData_, barcodeFile_, barcodeHash_, barcodeCount_, barcodeMode_, barcodeQuality_); + + const auto rhsFields = std::tie( + other.id_, other.sequencingCenter_, other.date_, other.flowOrder_, other.keySequence_, + other.library_, other.programs_, other.platformModel_, other.predictedInsertSize_, + other.movieName_, other.sample_, other.readType_, other.bindingKit_, other.sequencingKit_, + other.basecallerVersion_, other.frameRateHz_, other.control_, other.ipdCodec_, + other.pulseWidthCodec_, other.hasBarcodeData_, other.barcodeFile_, other.barcodeHash_, + other.barcodeCount_, other.barcodeMode_, other.barcodeQuality_); + + return lhsFields == rhsFields && + boost::algorithm::equal(features_.cbegin(), features_.cend(), other.features_.cbegin(), + other.features_.cend()) && + boost::algorithm::equal(custom_.cbegin(), custom_.cend(), other.custom_.cbegin(), + other.custom_.cend()); +} + +bool ReadGroupInfo::operator<(const ReadGroupInfo& other) const { return id_ < other.id_; } + +size_t ReadGroupInfo::BarcodeCount() const +{ + if (!hasBarcodeData_) + throw std::runtime_error{ + "ReadGroupInfo: barcode count requested but barcode data is missing"}; + return barcodeCount_; +} + +ReadGroupInfo& ReadGroupInfo::BarcodeData(std::string barcodeFile, std::string barcodeHash, + size_t barcodeCount, BarcodeModeType barcodeMode, + BarcodeQualityType barcodeQuality) +{ + barcodeFile_ = std::move(barcodeFile); + barcodeHash_ = std::move(barcodeHash); + barcodeCount_ = barcodeCount; + barcodeMode_ = barcodeMode; + barcodeQuality_ = barcodeQuality; + hasBarcodeData_ = true; + return *this; +} + +std::string ReadGroupInfo::BarcodeFile() const +{ + if (!hasBarcodeData_) + throw std::runtime_error{ + "ReadGroupInfo: barcode file requested but barcode data is missing"}; + return barcodeFile_; +} + +std::string ReadGroupInfo::BarcodeHash() const +{ + if (!hasBarcodeData_) + throw std::runtime_error{ + "ReadGroupInfo: barcode hash requested but barcode data is missing"}; + return barcodeHash_; +} + +BarcodeModeType ReadGroupInfo::BarcodeMode() const +{ + if (!hasBarcodeData_) + throw std::runtime_error{ + "ReadGroupInfo: barcode mode requested but barcode data is missing"}; + return barcodeMode_; +} + +BarcodeQualityType ReadGroupInfo::BarcodeQuality() const +{ + if (!hasBarcodeData_) + throw std::runtime_error{ + "ReadGroupInfo: barcode quality requested but barcode data is missing"}; + return barcodeQuality_; +} + +boost::optional ReadGroupInfo::BarcodeForward() const +{ + const auto barcodes = Barcodes(); + if (barcodes) return barcodes->first; + return boost::make_optional(false, uint16_t{0}); +} + +boost::optional ReadGroupInfo::BarcodeReverse() const +{ + const auto barcodes = Barcodes(); + if (barcodes) return barcodes->second; + return boost::make_optional(false, uint16_t{0}); +} + +boost::optional> ReadGroupInfo::Barcodes() const { return barcodes_; } + +std::string ReadGroupInfo::BasecallerVersion() const { return basecallerVersion_; } + +ReadGroupInfo& ReadGroupInfo::BasecallerVersion(std::string versionNumber) +{ + if (basecallerVersion_ != versionNumber) { + basecallerVersion_ = std::move(versionNumber); + sequencingChemistry_.clear(); // reset cached chemistry name + } + return *this; +} + +std::string ReadGroupInfo::BaseFeatureTag(BaseFeature feature) const +{ + const auto iter = features_.find(feature); + if (iter == features_.end()) return {}; + return iter->second; +} + +ReadGroupInfo& ReadGroupInfo::BaseFeatureTag(BaseFeature feature, std::string tag) +{ + features_[feature] = std::move(tag); + return *this; +} + +std::string ReadGroupInfo::BaseId() const { return baseId_; } + +std::string ReadGroupInfo::BindingKit() const { return bindingKit_; } + +ReadGroupInfo& ReadGroupInfo::BindingKit(std::string kitNumber) +{ + if (bindingKit_ != kitNumber) { + bindingKit_ = std::move(kitNumber); + sequencingChemistry_.clear(); // reset cached chemistry name + } + return *this; +} + +ReadGroupInfo& ReadGroupInfo::ClearBarcodeData() +{ + barcodeFile_.clear(); + barcodeHash_.clear(); + hasBarcodeData_ = false; + return *this; +} + +ReadGroupInfo& ReadGroupInfo::ClearBaseFeatures() +{ + features_.clear(); + return *this; +} + +bool ReadGroupInfo::Control() const { return control_; } + +ReadGroupInfo& ReadGroupInfo::Control(bool ctrl) +{ + control_ = ctrl; + return *this; +} + +std::map ReadGroupInfo::CustomTags() const { return custom_; } + +ReadGroupInfo& ReadGroupInfo::CustomTags(std::map custom) +{ + custom_ = std::move(custom); + return *this; +} + +std::string ReadGroupInfo::Date() const { return date_; } + +ReadGroupInfo& ReadGroupInfo::Date(std::string date) +{ + date_ = std::move(date); + return *this; +} + +void ReadGroupInfo::DecodeBarcodeKey(const std::string& key, std::string value) +{ + if (key == token_BF) + barcodeFile_ = std::move(value); + else if (key == token_BH) + barcodeHash_ = std::move(value); + else if (key == token_BC) + barcodeCount_ = std::stoul(value); + else if (key == token_BM) + barcodeMode_ = BarcodeModeFromName(value); + else if (key == token_BQ) + barcodeQuality_ = BarcodeQualityFromName(value); +} + +void ReadGroupInfo::DecodeFrameCodecKey(const std::string& key, std::string value) +{ + const auto keyParts = Split(key, ':'); + if (keyParts.size() == 2) { + const auto& subkey = keyParts.at(0); + if (subkey == feature_IP) { + ipdCodec_ = FrameCodecFromName(keyParts.at(1)); + features_[BaseFeature::IPD] = std::move(value); + } else if (subkey == feature_PW) { + pulseWidthCodec_ = FrameCodecFromName(keyParts.at(1)); + features_[BaseFeature::PULSE_WIDTH] = std::move(value); + } + } +} + +void ReadGroupInfo::DecodeSamDescription(const std::string& description) +{ + const auto tokens = Split(description, ';'); + if (tokens.empty()) return; + + // iterate over tokens + for (const auto& token : tokens) { + + const auto foundEqual = token.find('='); + if (foundEqual == std::string::npos) continue; + + const auto key = token.substr(0, foundEqual); + auto value = token.substr(foundEqual + 1); + + // 'mandatory' items + // clang-format off + if (key == token_RT) readType_ = std::move(value); + else if (key == token_BK) bindingKit_ = std::move(value); + else if (key == token_BV) basecallerVersion_ = std::move(value); + else if (key == token_SK) sequencingKit_ = std::move(value); + else if (key == token_FR) frameRateHz_ = std::move(value); + else if (key == token_CT) control_ = (value == "TRUE"); + // clang-format on + + // base features + else if (IsBaseFeature(key)) + features_[BaseFeatureFromName(key)] = std::move(value); + + // barcode data + else if (IsLikelyBarcodeKey(key)) + DecodeBarcodeKey(key, std::move(value)); + + // frame codecs + else + DecodeFrameCodecKey(key, std::move(value)); + } + + hasBarcodeData_ = !barcodeFile_.empty(); +} + +std::string ReadGroupInfo::EncodeSamDescription() const +{ + constexpr static const char SEP = ';'; + constexpr static const char COLON = ':'; + constexpr static const char EQ = '='; + + std::string result{token_RT + EQ + readType_}; + + std::string featureName; + for (const auto& feature : features_) { + + featureName = BaseFeatureName(feature.first); + if (featureName.empty() || feature.second.empty()) + continue; + else if (featureName == feature_IP) { + featureName.push_back(COLON); + featureName.append(FrameCodecName(ipdCodec_)); + } else if (featureName == feature_PW) { + featureName.push_back(COLON); + featureName.append(FrameCodecName(pulseWidthCodec_)); + } + result.append(SEP + featureName + EQ + feature.second); + } + + // clang-format off + if (!bindingKit_.empty()) result.append(SEP + token_BK + EQ + bindingKit_); + if (!sequencingKit_.empty()) result.append(SEP + token_SK + EQ + sequencingKit_); + if (!basecallerVersion_.empty()) result.append(SEP + token_BV + EQ + basecallerVersion_); + if (!frameRateHz_.empty()) result.append(SEP + token_FR + EQ + frameRateHz_); + if (control_) result.append(SEP + token_CT + EQ + (control_ ? "TRUE" : "FALSE")); + // clang-format on + + if (hasBarcodeData_) { + const std::string barcodeData{SEP + token_BF + EQ + barcodeFile_ + SEP + token_BH + EQ + + barcodeHash_ + SEP + token_BC + EQ + + std::to_string(barcodeCount_) + SEP + token_BM + EQ + + BarcodeModeName(barcodeMode_) + SEP + token_BQ + EQ + + BarcodeQualityName(barcodeQuality_)}; + result.append(barcodeData); + } + + return result; +} + +std::string ReadGroupInfo::FlowOrder() const { return flowOrder_; } + +ReadGroupInfo& ReadGroupInfo::FlowOrder(std::string order) +{ + flowOrder_ = std::move(order); + return *this; +} + +std::string ReadGroupInfo::FrameRateHz() const { return frameRateHz_; } + +ReadGroupInfo& ReadGroupInfo::FrameRateHz(std::string frameRateHz) +{ + frameRateHz_ = std::move(frameRateHz); + return *this; +} + +ReadGroupInfo ReadGroupInfo::FromSam(const std::string& sam) +{ + // pop off '@RG\t', then split rest of line into tokens + const auto tokens = Split(sam.substr(4), '\t'); + if (tokens.empty()) return {}; + + ReadGroupInfo rg; + std::map custom; + + for (const auto& token : tokens) { + const auto tokenTag = token.substr(0, 2); + auto tokenValue = token.substr(3); + + // set read group info + // clang-format off + if (tokenTag == sam_ID) rg.Id(std::move(tokenValue)); + else if (tokenTag == sam_CN) rg.SequencingCenter(std::move(tokenValue)); + else if (tokenTag == sam_DT) rg.Date(std::move(tokenValue)); + else if (tokenTag == sam_FO) rg.FlowOrder(std::move(tokenValue)); + else if (tokenTag == sam_KS) rg.KeySequence(std::move(tokenValue)); + else if (tokenTag == sam_LB) rg.Library(std::move(tokenValue)); + else if (tokenTag == sam_PG) rg.Programs(std::move(tokenValue)); + else if (tokenTag == sam_PI) rg.PredictedInsertSize(std::move(tokenValue)); + else if (tokenTag == sam_PU) rg.MovieName(std::move(tokenValue)); + else if (tokenTag == sam_SM) rg.Sample(std::move(tokenValue)); + else if (tokenTag == sam_DS) rg.DecodeSamDescription(std::move(tokenValue)); + else if (tokenTag == sam_PM) rg.PlatformModel(PlatformModelFromName(std::move(tokenValue))); + // clang-format on + + // if not platform name (always "PACBIO" for us), store as a custom tag + else if (tokenTag != sam_PL) + custom[tokenTag] = std::move(tokenValue); + } + rg.CustomTags(std::move(custom)); + + return rg; +} + +std::string ReadGroupInfo::GetBaseId(const std::string& id) +{ + const auto slashAt = id.find('/'); + if (slashAt == std::string::npos) + return id; + else + return id.substr(0, slashAt); +} + +bool ReadGroupInfo::HasBarcodeData() const { return hasBarcodeData_; } + +bool ReadGroupInfo::HasBaseFeature(BaseFeature feature) const +{ + return features_.find(feature) != features_.end(); +} + +std::string ReadGroupInfo::Id() const { return id_; } + +ReadGroupInfo& ReadGroupInfo::Id(const std::string& movieName, const std::string& readType) +{ + return Id(MakeReadGroupId(movieName, readType)); +} + +ReadGroupInfo& ReadGroupInfo::Id(std::string id) +{ + barcodes_.reset(); + + // maybe parse for barcode labels + const auto slashAt = id.find('/'); + if (slashAt != std::string::npos) { + // looks like we do, parse & store + const auto tokens = Split(id.substr(slashAt + 1), '-'); + if (tokens.size() != 3) { + throw std::runtime_error{ + "ReadGroupInfo: could not fetch barcodes from malformatted read group ID: " + id + + " Must be in the form: {RGID_STRING}/{bcForward}--{bcReverse}"}; + } + + // catch here so we can give more informative message + try { + barcodes_ = std::pair(static_cast(std::stoul(tokens[0])), + static_cast(std::stoul(tokens[2]))); + } catch (std::exception& e) { + throw std::runtime_error{ + "ReadGroupInfo: could not fetch barcodes from malformatted read group ID: " + id + + " Must be in the form: {RGID_STRING}/{bcForward}--{bcReverse}"}; + } + } + + baseId_ = id.substr(0, slashAt); + id_ = std::move(id); + return *this; +} + +int32_t ReadGroupInfo::IdToInt(const std::string& rgId) +{ + const auto id = GetBaseId(rgId); + const uint32_t rawid = std::stoul(id, nullptr, 16); + return static_cast(rawid); +} + +std::string ReadGroupInfo::IntToId(const int32_t id) +{ + std::ostringstream s; + s << std::setfill('0') << std::setw(8) << std::hex << id; + return s.str(); +} + +FrameCodec ReadGroupInfo::IpdCodec() const { return ipdCodec_; } + +ReadGroupInfo& ReadGroupInfo::IpdCodec(FrameCodec codec, std::string tag) +{ + // store desired codec type + ipdCodec_ = std::move(codec); + + // update base features map + const std::string actualTag = (tag.empty() ? "ip" : std::move(tag)); + BaseFeatureTag(BaseFeature::IPD, actualTag); + return *this; +} + +bool ReadGroupInfo::IsValid() const { return !id_.empty(); } + +std::string ReadGroupInfo::KeySequence() const { return keySequence_; } + +ReadGroupInfo& ReadGroupInfo::KeySequence(std::string sequence) +{ + keySequence_ = std::move(sequence); + return *this; +} + +std::string ReadGroupInfo::Library() const { return library_; } + +ReadGroupInfo& ReadGroupInfo::Library(std::string library) +{ + library_ = std::move(library); + return *this; +} + +std::string ReadGroupInfo::MovieName() const { return movieName_; } + +ReadGroupInfo& ReadGroupInfo::MovieName(std::string movieName) +{ + movieName_ = std::move(movieName); + return *this; +} + +std::string ReadGroupInfo::Platform() const { return std::string("PACBIO"); } + +PlatformModelType ReadGroupInfo::PlatformModel() const { return platformModel_; } + +ReadGroupInfo& ReadGroupInfo::PlatformModel(PlatformModelType platform) +{ + platformModel_ = platform; + return *this; +} + +std::string ReadGroupInfo::PredictedInsertSize() const { return predictedInsertSize_; } + +ReadGroupInfo& ReadGroupInfo::PredictedInsertSize(std::string size) +{ + predictedInsertSize_ = std::move(size); + return *this; +} + +std::string ReadGroupInfo::Programs() const { return programs_; } + +ReadGroupInfo& ReadGroupInfo::Programs(std::string programs) +{ + programs_ = std::move(programs); + return *this; +} + +FrameCodec ReadGroupInfo::PulseWidthCodec() const { return pulseWidthCodec_; } + +ReadGroupInfo& ReadGroupInfo::PulseWidthCodec(FrameCodec codec, std::string tag) +{ + // store desired codec type + pulseWidthCodec_ = std::move(codec); + + // update base features map + const std::string actualTag = (tag.empty() ? "pw" : std::move(tag)); + BaseFeatureTag(BaseFeature::PULSE_WIDTH, actualTag); + return *this; +} + +std::string ReadGroupInfo::ReadType() const { return readType_; } + +ReadGroupInfo& ReadGroupInfo::ReadType(std::string type) +{ + readType_ = std::move(type); + return *this; +} + +ReadGroupInfo& ReadGroupInfo::RemoveBaseFeature(BaseFeature feature) +{ + const auto iter = features_.find(feature); + if (iter != features_.end()) features_.erase(iter); + return *this; +} + +std::string ReadGroupInfo::Sample() const { return sample_; } + +ReadGroupInfo& ReadGroupInfo::Sample(std::string sample) +{ + sample_ = std::move(sample); + return *this; +} + +std::string ReadGroupInfo::SequencingCenter() const { return sequencingCenter_; } + +ReadGroupInfo& ReadGroupInfo::SequencingCenter(std::string center) +{ + sequencingCenter_ = std::move(center); + return *this; +} + +std::string ReadGroupInfo::SequencingChemistry() const +{ + if (!sequencingChemistry_.empty()) return sequencingChemistry_; + return sequencingChemistry_ = + SequencingChemistryFromTriple(BindingKit(), SequencingKit(), BasecallerVersion()); +} + +std::string ReadGroupInfo::SequencingChemistryFromTriple(const std::string& bindingKit, + const std::string& sequencingKit, + const std::string& basecallerVersion) +{ + const auto verFields = Split(basecallerVersion, '.'); + if (verFields.size() < 2) + throw std::runtime_error{"ReadGroupInfo: basecaller version is too short: " + + basecallerVersion}; + const std::string version{verFields.at(0) + '.' + verFields.at(1)}; + + // check updated table first, if it exists (empty if not), overriding the built-in lookup + for (const auto& row : GetChemistryTableFromEnv()) { + if (bindingKit == row[0] && sequencingKit == row[1] && version == row[2]) return row[3]; + } + + for (const auto& row : BuiltInChemistryTable()) { + if (bindingKit == row[0] && sequencingKit == row[1] && version == row[2]) return row[3]; + } + + // not found + throw InvalidSequencingChemistryException{bindingKit, sequencingKit, basecallerVersion}; +} + +std::string ReadGroupInfo::SequencingKit() const { return sequencingKit_; } + +ReadGroupInfo& ReadGroupInfo::SequencingKit(std::string kitNumber) +{ + if (sequencingKit_ != kitNumber) { + sequencingKit_ = std::move(kitNumber); + sequencingChemistry_.clear(); // reset cached chemistry name + } + return *this; +} + +std::string ReadGroupInfo::ToSam(const ReadGroupInfo& rg) { return rg.ToSam(); } + +std::string ReadGroupInfo::ToSam() const +{ + std::ostringstream out; + out << "@RG" << MakeSamTag(sam_ID, id_) << MakeSamTag(sam_PL, Platform()); + + const auto description = EncodeSamDescription(); + if (!description.empty()) out << MakeSamTag(sam_DS, description); + + // clang-format off + if (!sequencingCenter_.empty()) out << MakeSamTag(sam_CN, sequencingCenter_); + if (!date_.empty()) out << MakeSamTag(sam_DT, date_); + if (!flowOrder_.empty()) out << MakeSamTag(sam_FO, flowOrder_); + if (!keySequence_.empty()) out << MakeSamTag(sam_KS, keySequence_); + if (!library_.empty()) out << MakeSamTag(sam_LB, library_); + if (!programs_.empty()) out << MakeSamTag(sam_PG, programs_); + if (!predictedInsertSize_.empty()) out << MakeSamTag(sam_PI, predictedInsertSize_); + if (!movieName_.empty()) out << MakeSamTag(sam_PU, movieName_); + if (!sample_.empty()) out << MakeSamTag(sam_SM, sample_); + if (barcodes_) + { + out << '\t' << sam_BC << ':' + << barcodes_->first << "--" << barcodes_->second; + } + // clang-format on + + out << MakeSamTag(sam_PM, PlatformModelName(platformModel_)); + + // append any custom tags + for (const auto& attribute : custom_) + out << MakeSamTag(attribute.first, attribute.second); + + return out.str(); +} + +std::string MakeReadGroupId(const std::string& movieName, const std::string& readType) +{ + return MD5Hash(movieName + "//" + readType).substr(0, 8); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/RecordType.cpp b/src/RecordType.cpp new file mode 100644 index 0000000..02b29e6 --- /dev/null +++ b/src/RecordType.cpp @@ -0,0 +1,45 @@ +// File Description +/// \file RecordType.h +/// \brief Implements the RecordType-related methods +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/RecordType.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +bool IsCcsOrTranscript(const RecordType type) +{ + return (type == RecordType::CCS) || (type == RecordType::TRANSCRIPT); +} + +std::string ToString(const RecordType type) +{ + // clang-format off + static const auto lookup = std::map + { + { RecordType::ZMW, "ZMW" }, + { RecordType::HQREGION, "HQREGION" }, + { RecordType::SUBREAD, "SUBREAD" }, + { RecordType::CCS, "CCS" }, + { RecordType::SCRAP, "SCRAP" }, + { RecordType::TRANSCRIPT, "TRANSCRIPT" }, + { RecordType::UNKNOWN, "UNKNOWN" } + }; + // clang-format on + + try { + return lookup.at(type); + } catch (std::exception&) { + throw std::runtime_error{"BamRecordType: unknown type"}; + } +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/SamTagCodec.cpp b/src/SamTagCodec.cpp new file mode 100644 index 0000000..47bda7e --- /dev/null +++ b/src/SamTagCodec.cpp @@ -0,0 +1,281 @@ +// File Description +/// \file SamTagCodec.h +/// \brief Implements the SamTagCodec class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/SamTagCodec.h" + +#include +#include +#include + +#include + +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { +namespace { + +std::vector readFloatSamMultiValue(const std::string& data) +{ + std::vector result; + auto* c = const_cast(data.c_str()); + const char* end = c + data.length(); + while (c + 1 < end) + result.emplace_back(strtof(c + 1, &c)); + return result; +} + +template +std::vector readSignedSamMultiValue(const std::string& data) +{ + std::vector result; + auto* c = const_cast(data.c_str()); + const char* end = c + data.length(); + while (c + 1 < end) + result.emplace_back(strtol(c + 1, &c, 0)); + return result; +} + +template +std::vector readUnsignedSamMultiValue(const std::string& data) +{ + std::vector result; + auto* c = const_cast(data.c_str()); + const char* end = c + data.length(); + while (c + 1 < end) + result.emplace_back(strtoul(c + 1, &c, 0)); + return result; +} + +} // namespace + +TagCollection SamTagCodec::Decode(const std::string& tagString) +{ + TagCollection tags; + + const auto tokens = Split(tagString, '\t'); + for (const auto& token : tokens) { + if (token.size() < 6) // TT:t:X + continue; + + const auto name = token.substr(0, 2); + const auto type = token.at(3); + const auto remainder = token.substr(5); + if (remainder.empty()) throw std::runtime_error{"SamTagCodec: malformatted tag: " + token}; + + switch (type) { + + // technically only 'A' is allowed in SAM chars, + // but we'll be a little permissive + case 'A': + case 'a': { + tags[name] = Tag{static_cast(remainder[0], TagModifier::ASCII_CHAR)}; + break; + } + + // technically only 'i' is allowed in SAM ints, but we'll be a little + // permissive since SAM might be a bit more "user-edited" than BAM + case 'c': + case 'C': + case 's': + case 'S': + case 'i': + case 'I': { + // check out boost::numeric cast for these conversions + + // negative value (force signed int) + if (remainder[0] == '-') { + const auto x = boost::lexical_cast(remainder); + if (x >= std::numeric_limits::min()) + tags[name] = static_cast(x); + else if (x >= std::numeric_limits::min()) + tags[name] = static_cast(x); + else + tags[name] = x; + } + + // unsigned int + else { + const auto x = boost::lexical_cast(remainder); + if (x <= std::numeric_limits::max()) + tags[name] = static_cast(x); + else if (x <= std::numeric_limits::max()) + tags[name] = static_cast(x); + else + tags[name] = x; + } + break; + } + + case 'f': { + tags[name] = boost::lexical_cast(remainder); + break; + } + + case 'Z': { + tags[name] = remainder; + break; + } + + case 'H': { + tags[name] = Tag(remainder, TagModifier::HEX_STRING); + break; + } + + case 'B': { + const auto elementType = remainder[0]; + const auto arrayData = remainder.substr(1); + switch (elementType) { + case 'c': + tags[name] = readSignedSamMultiValue(arrayData); + break; + case 'C': + tags[name] = readUnsignedSamMultiValue(arrayData); + break; + case 's': + tags[name] = readSignedSamMultiValue(arrayData); + break; + case 'S': + tags[name] = readUnsignedSamMultiValue(arrayData); + break; + case 'i': + tags[name] = readSignedSamMultiValue(arrayData); + break; + case 'I': + tags[name] = readUnsignedSamMultiValue(arrayData); + break; + case 'f': + tags[name] = readFloatSamMultiValue(arrayData); + break; + default: + throw std::runtime_error{ + "SamTagCodec: unsupported array-tag-type encountered: " + + std::string{1, elementType}}; + } + break; + } + + // unsupported SAM tag type + default: + throw std::runtime_error{"SamTagCodec: unsupported tag-type encountered: " + + std::string{1, type}}; + } + } + + return tags; +} + +std::string SamTagCodec::Encode(const std::string& name, const PacBio::BAM::Tag& tag) +{ + // upfront checks + if (name.size() != 2) { + throw std::runtime_error{"SamTagCodec: malformatted tag name: " + name}; + } + if (tag.IsNull()) return {}; + + // ":" + std::ostringstream result; + result << name << ':'; + + // ASCII char + if (tag.HasModifier(TagModifier::ASCII_CHAR)) { + const auto c = tag.ToAscii(); + if (c != '\0') { + result << "A:" << c; + return result.str(); + } + } + + // ":" for all other data + switch (tag.Type()) { + case TagDataType::INT8: + result << "i:" << static_cast(tag.ToInt8()); + break; + case TagDataType::UINT8: + result << "i:" << static_cast(tag.ToUInt8()); + break; + case TagDataType::INT16: + result << "i:" << tag.ToInt16(); + break; + case TagDataType::UINT16: + result << "i:" << tag.ToUInt16(); + break; + case TagDataType::INT32: + result << "i:" << tag.ToInt32(); + break; + case TagDataType::UINT32: + result << "i:" << tag.ToUInt32(); + break; + case TagDataType::FLOAT: + result << "f:" << tag.ToFloat(); + break; + case TagDataType::STRING: + result << (tag.HasModifier(TagModifier::HEX_STRING) ? 'H' : 'Z') << ':' + << tag.ToString(); + break; + case TagDataType::INT8_ARRAY: + result << "B:c"; + for (const int8_t x : tag.ToInt8Array()) + result << ',' << static_cast(x); + break; + case TagDataType::UINT8_ARRAY: + result << "B:C"; + for (const uint8_t x : tag.ToUInt8Array()) + result << ',' << static_cast(x); + break; + case TagDataType::INT16_ARRAY: + result << "B:s"; + for (const int16_t x : tag.ToInt16Array()) + result << ',' << x; + break; + case TagDataType::UINT16_ARRAY: + result << "B:S"; + for (const uint16_t x : tag.ToUInt16Array()) + result << ',' << x; + break; + case TagDataType::INT32_ARRAY: + result << "B:i"; + for (const int32_t x : tag.ToInt32Array()) + result << ',' << x; + break; + case TagDataType::UINT32_ARRAY: + result << "B:I"; + for (const uint32_t x : tag.ToUInt32Array()) + result << ',' << x; + break; + case TagDataType::FLOAT_ARRAY: + result << "B:f"; + for (const float x : tag.ToFloatArray()) + result << ',' << x; + break; + default: + throw std::runtime_error{"SamTagCodec: unsupported tag-type encountered: " + + std::to_string(static_cast(tag.Type()))}; + } + return result.str(); +} + +std::string SamTagCodec::Encode(const TagCollection& tags) +{ + std::ostringstream result; + for (const auto& tagIter : tags) { + const std::string& name = tagIter.first; + const Tag& tag = tagIter.second; + if (!result.str().empty()) result << '\t'; + result << Encode(name, tag); + } + return result.str(); +} + +std::string MakeSamTag(std::string tag, std::string value) +{ + return '\t' + std::move(tag) + ':' + std::move(value); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/SamWriter.cpp b/src/SamWriter.cpp new file mode 100644 index 0000000..e3a78b9 --- /dev/null +++ b/src/SamWriter.cpp @@ -0,0 +1,116 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/SamWriter.h" + +#include +#include +#include +#include + +#include +#include + +#include "Autovalidate.h" +#include "FileProducer.h" +#include "MemoryUtils.h" +#include "pbbam/Validator.h" + +namespace PacBio { +namespace BAM { + +class SamWriter::SamWriterPrivate : public FileProducer +{ +public: + SamWriterPrivate(std::string filename, const std::shared_ptr rawHeader) + : FileProducer{std::move(filename)}, header_{rawHeader} + { + if (!header_) throw std::runtime_error{"SamWriter: null header provided"}; + + // open file + const auto& usingFilename = TempFilename(); + const std::string mode(1, 'w'); + file_.reset(sam_open(usingFilename.c_str(), mode.c_str())); + if (!file_) + throw std::runtime_error{"SamWriter: could not open file for writing: " + + usingFilename}; + + // write header + const auto ret = sam_hdr_write(file_.get(), header_.get()); + if (ret != 0) + throw std::runtime_error{"SamWriter: could not write header to file: " + usingFilename}; + } + + void Write(BamRecord record) + { +#if PBBAM_AUTOVALIDATE + Validator::Validate(record); +#endif + + const auto rawRecord = BamRecordMemory::GetRawData(record); + + // store bin number + // min_shift=14 & n_lvls=5 are SAM/BAM "magic numbers" + rawRecord->core.bin = hts_reg2bin(rawRecord->core.pos, bam_endpos(rawRecord.get()), 14, 5); + + // Maybe adjust location of long CIGAR (>65535 ops) data, depending on the + // runtime htslib version. + // + // SAM formatting in htslib verions previous to 1.7 are unaware of the new + // long CIGAR implementation ("CG") tag. So we need to move that back to the + // "standard" field so that SAM output is correct. Versions >=1.7 properly + // display long CIGARs. + // + // This transform will become unecessary when we drop support for htslib pre-v1.7. + // + static const bool has_native_long_cigar_support = DoesHtslibSupportLongCigar(); + const auto cigar = record.CigarData(); + if (!has_native_long_cigar_support && cigar.size() > 65535) { + if (record.Impl().HasTag("CG")) record.Impl().RemoveTag("CG"); + record.Impl().SetCigarData(cigar); + } + + // write record to file + const int ret = sam_write1(file_.get(), header_.get(), rawRecord.get()); + if (ret <= 0) throw std::runtime_error{"SamWriter: could not write record"}; + } + + std::unique_ptr file_; + std::shared_ptr header_; +}; + +static_assert(!std::is_copy_constructible::value, + "SamWriter(const SamWriter&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "SamWriter& operator=(const SamWriter&) is not = delete"); + +SamWriter::SamWriter(std::string filename, const BamHeader& header) + : IRecordWriter() + , d_{std::make_unique(std::move(filename), + BamHeaderMemory::MakeRawHeader(header))} +{ +#if PBBAM_AUTOVALIDATE + Validator::Validate(header); +#endif +} + +SamWriter::SamWriter(SamWriter&&) noexcept = default; + +SamWriter& SamWriter::operator=(SamWriter&&) noexcept = default; + +SamWriter::~SamWriter() = default; + +void SamWriter::TryFlush() +{ + const auto ret = d_->file_.get()->fp.hfile; + if (ret != nullptr) + throw std::runtime_error{"SamWriter: could not flush output buffer contents"}; +} + +void SamWriter::Write(const BamRecord& record) { d_->Write(record); } + +void SamWriter::Write(const BamRecordImpl& recordImpl) { Write(BamRecord{recordImpl}); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/SequenceInfo.cpp b/src/SequenceInfo.cpp new file mode 100644 index 0000000..519e55e --- /dev/null +++ b/src/SequenceInfo.cpp @@ -0,0 +1,180 @@ +// File Description +/// \file SequenceInfo.cpp +/// \brief Implements the SequenceInfo class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/SequenceInfo.h" + +#include +#include +#include +#include +#include +#include + +#include "pbbam/SamTagCodec.h" +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { +namespace { + +const std::string token_SN{"SN"}; +const std::string token_LN{"LN"}; +const std::string token_AS{"AS"}; +const std::string token_M5{"M5"}; +const std::string token_SP{"SP"}; +const std::string token_UR{"UR"}; + +} // anonymous + +static_assert(std::is_copy_constructible::value, + "SequenceInfo(const SequenceInfo&) is not = default"); +static_assert(std::is_copy_assignable::value, + "SequenceInfo& operator=(const SequenceInfo&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "SequenceInfo(SequenceInfo&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +SequenceInfo::SequenceInfo(std::string name, std::string length) + : name_(std::move(name)), length_(std::move(length)) +{ +} + +bool SequenceInfo::operator==(const SequenceInfo& other) const +{ + return std::tie(assemblyId_, checksum_, length_, name_, species_, uri_, custom_) == + std::tie(other.assemblyId_, other.checksum_, other.length_, other.name_, other.species_, + other.uri_, other.custom_); +} + +bool SequenceInfo::operator!=(const SequenceInfo& other) const { return !(*this == other); } + +std::string SequenceInfo::AssemblyId() const { return assemblyId_; } + +SequenceInfo& SequenceInfo::AssemblyId(std::string id) +{ + assemblyId_ = std::move(id); + return *this; +} + +std::string SequenceInfo::Checksum() const { return checksum_; } + +SequenceInfo& SequenceInfo::Checksum(std::string checksum) +{ + checksum_ = std::move(checksum); + return *this; +} + +std::map SequenceInfo::CustomTags() const { return custom_; } + +SequenceInfo& SequenceInfo::CustomTags(std::map custom) +{ + custom_ = std::move(custom); + return *this; +} + +SequenceInfo SequenceInfo::FromSam(const std::string& sam) +{ + // pop off '@SQ\t', then split rest of line into tokens + const auto tokens = Split(sam.substr(4), '\t'); + if (tokens.empty()) return {}; + + SequenceInfo seq; + std::map custom; + + // iterate over tokens + for (const auto& token : tokens) { + const auto tokenTag = token.substr(0, 2); + auto tokenValue = token.substr(3); + + // set sequence info + // clang-format off + if (tokenTag == token_SN) seq.Name(std::move(tokenValue)); + else if (tokenTag == token_LN) seq.Length(std::move(tokenValue)); + else if (tokenTag == token_AS) seq.AssemblyId(std::move(tokenValue)); + else if (tokenTag == token_M5) seq.Checksum(std::move(tokenValue)); + else if (tokenTag == token_SP) seq.Species(std::move(tokenValue)); + else if (tokenTag == token_UR) seq.Uri(std::move(tokenValue)); + // clang-format on + + // otherwise, "custom" tag + else + custom[tokenTag] = std::move(tokenValue); + } + + seq.CustomTags(std::move(custom)); + return seq; +} + +bool SequenceInfo::IsValid() const +{ + if (name_.empty()) return false; + + // use long instead of int32_t, just to make sure we can catch overflow + const long l = atol(length_.c_str()); + return l >= 0 && l <= std::numeric_limits::max(); +} + +std::string SequenceInfo::Length() const { return length_; } + +SequenceInfo& SequenceInfo::Length(std::string length) +{ + length_ = std::move(length); + return *this; +} + +std::string SequenceInfo::Name() const { return name_; } + +SequenceInfo& SequenceInfo::Name(std::string name) +{ + name_ = std::move(name); + return *this; +} + +std::string SequenceInfo::Species() const { return species_; } + +SequenceInfo& SequenceInfo::Species(std::string species) +{ + species_ = std::move(species); + return *this; +} + +std::string SequenceInfo::ToSam(const SequenceInfo& seq) { return seq.ToSam(); } + +std::string SequenceInfo::ToSam() const +{ + std::ostringstream out; + out << "@SQ" << MakeSamTag(token_SN, name_); + + // clang-format off + if (!length_.empty()) out << MakeSamTag(token_LN, length_); + if (!assemblyId_.empty()) out << MakeSamTag(token_AS, assemblyId_); + if (!checksum_.empty()) out << MakeSamTag(token_M5, checksum_); + if (!species_.empty()) out << MakeSamTag(token_SP, species_); + if (!uri_.empty()) out << MakeSamTag(token_UR, uri_); + // clang-format on + + // append any custom tags + for (auto&& attribute : custom_) + out << MakeSamTag(std::move(attribute.first), std::move(attribute.second)); + + return out.str(); +} + +std::string SequenceInfo::Uri() const { return uri_; } + +SequenceInfo& SequenceInfo::Uri(std::string uri) +{ + uri_ = std::move(uri); + return *this; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/SequenceUtils.h b/src/SequenceUtils.h new file mode 100644 index 0000000..8bad6ca --- /dev/null +++ b/src/SequenceUtils.h @@ -0,0 +1,126 @@ +// Author: Derek Barnett + +#ifndef SEQUENCEUTILS_H +#define SEQUENCEUTILS_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { + +inline char Complement(const char character) +{ + constexpr const std::array lookupTable{ + {/* 0 - 7: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 8 - 15: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 16 - 23: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 24 - 31: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 32 - 39: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 40 - 47: */ 0, 0, '*', 0, 0, '-', 0, 0, + /* 48 - 55: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 56 - 63: */ 0, 0, 0, 0, 0, 0, 0, 0, + + /* 64 - 71: */ 0, 'T', 'V', 'G', 'H', 0, 0, 'C', + /* 72 - 79: */ 'D', 0, 0, 'M', 0, 'K', 'N', 0, + /* 80 - 87: */ 0, 0, 'Y', 'S', 'A', 'A', 'B', 'W', + /* 88 - 95: */ 0, 'R', 0, 0, 0, 0, 0, 0, + + /* 96 - 103: */ 0, 'T', 'V', 'G', 'H', 0, 0, 'C', + /* 104 - 111: */ 'D', 0, 0, 'M', 0, 'K', 'N', 0, + /* 112 - 119: */ 0, 0, 'Y', 'S', 'A', 'A', 'B', 'W', + /* 120 - 127: */ 0, 'R', 0, 0, 0, 0, 0, 0, + + /* 128 - 135: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 136 - 143: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 144 - 151: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 152 - 159: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 160 - 167: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 168 - 175: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 176 - 183: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 184 - 191: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 192 - 199: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 200 - 207: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 208 - 215: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 216 - 223: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 224 - 231: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 232 - 239: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 240 - 247: */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 248 - 255: */ 0, 0, 0, 0, 0, 0, 0, 0}}; + + return lookupTable[static_cast(character)]; +} + +template +void Reverse(T& input) +{ + std::reverse(input.begin(), input.end()); +} + +template +T MaybeReverse(T&& input, bool reverse) +{ + if (reverse) std::reverse(input.begin(), input.end()); + return input; +} + +template +T Reversed(const T& input) +{ + T result = input; + Reverse(result); + return result; +} +inline void ReverseComplement(std::string& seq) +{ + std::transform(seq.begin(), seq.end(), seq.begin(), Complement); + Reverse(seq); +} + +inline std::string MaybeReverseComplement(std::string&& seq, bool reverse) +{ + if (reverse) ReverseComplement(seq); + return std::move(seq); +} + +/// Reverse complement a DNA sequence case-sensitive +inline void ReverseComplementCaseSens(std::string& seq) +{ + const std::string original = seq; + constexpr const static int8_t rc_table[128] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 42, 4, 4, 45, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 84, 4, 71, 4, 4, 4, 67, 4, 4, 4, 4, 4, 4, + 78, 4, 4, 4, 4, 4, 65, 65, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 116, 4, 103, 4, 4, 4, 99, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 97, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + std::string reverseCompl(original.length(), 'N'); + for (uint32_t i = 0; i < original.length(); ++i) + reverseCompl[original.length() - i - 1] = + static_cast(rc_table[static_cast(original[i])]); + seq = reverseCompl; +} + +inline std::string MaybeReverseComplementCaseSens(std::string&& seq, bool reverse) +{ + if (reverse) ReverseComplementCaseSens(seq); + return std::move(seq); +} + +inline std::string ReverseComplemented(const std::string& input) +{ + std::string result = input; + ReverseComplement(result); + return result; +} + +} // namespace BAM +} // namespace PacBio + +#endif // SEQUENCEUTILS_H diff --git a/src/StringUtilities.cpp b/src/StringUtilities.cpp new file mode 100644 index 0000000..622d73c --- /dev/null +++ b/src/StringUtilities.cpp @@ -0,0 +1,48 @@ +// File Description +/// \file SequenceInfo.cpp +/// \brief Implements the SequenceInfo class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/StringUtilities.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +std::string Join(const std::vector& tokens, const char delim) +{ + std::string result; + bool first = true; + for (const auto& token : tokens) { + if (!first) result += delim; + result += token; + first = false; + } + return result; +} + +std::vector Split(const std::string& line, const char delim) +{ + std::vector tokens; + std::istringstream lineStream(line); + std::string token; + while (std::getline(lineStream, token, delim)) + tokens.push_back(token); + return tokens; +} + +std::string RemoveAllWhitespace(std::string input) +{ + input.erase( + std::remove_if(input.begin(), input.end(), [](const char c) { return std::isspace(c); }), + input.end()); + return input; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/SubreadLengthQuery.cpp b/src/SubreadLengthQuery.cpp new file mode 100644 index 0000000..4eb35a9 --- /dev/null +++ b/src/SubreadLengthQuery.cpp @@ -0,0 +1,45 @@ +// File Description +/// \file SubreadLengthQuery.cpp +/// \brief Implements the SubreadLengthQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/SubreadLengthQuery.h" + +#include + +#include "pbbam/CompositeBamReader.h" +#include "pbbam/PbiFilterTypes.h" + +namespace PacBio { +namespace BAM { + +class SubreadLengthQuery::SubreadLengthQueryPrivate +{ +public: + SubreadLengthQueryPrivate(const int32_t length, const Compare::Type compareType, + const DataSet& dataset) + : reader_(PbiQueryLengthFilter(length, compareType), dataset) + { + } + + PbiFilterCompositeBamReader reader_; // unsorted +}; + +SubreadLengthQuery::SubreadLengthQuery(const int32_t length, const Compare::Type compareType, + const DataSet& dataset) + : internal::IQuery() + , d_{std::make_unique(length, compareType, dataset)} +{ +} + +SubreadLengthQuery::~SubreadLengthQuery() = default; + +bool SubreadLengthQuery::GetNext(BamRecord& r) { return d_->reader_.GetNext(r); } + +uint32_t SubreadLengthQuery::NumReads() const { return d_->reader_.NumReads(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/Tag.cpp b/src/Tag.cpp new file mode 100644 index 0000000..d0c322e --- /dev/null +++ b/src/Tag.cpp @@ -0,0 +1,401 @@ +// File Description +/// \file Tag.cpp +/// \brief Implements the Tag class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/Tag.h" + +#include +#include +#include + +#include + +namespace PacBio { +namespace BAM { +namespace { + +template +bool InAsciiRange(const T x) +{ + return (x >= 33 && x <= 127); +} + +struct AsciiConvertVisitor : public boost::static_visitor +{ + // only valid for numeric types - maybe even more restrictive? + char operator()(const int8_t& x) const { return Helper(x); } + char operator()(const uint8_t& x) const { return Helper(x); } + char operator()(const int16_t& x) const { return Helper(x); } + char operator()(const uint16_t& x) const { return Helper(x); } + char operator()(const int32_t& x) const { return Helper(x); } + char operator()(const uint32_t& x) const { return Helper(x); } + + // anything else always throws + template + char operator()(const T&) const + { + throw std::runtime_error{"Tag: cannot convert to ASCII"}; + return 0; + } + +private: + template + char Helper(const T& x) const + { + if (!InAsciiRange(x)) throw std::runtime_error{"Tag: char is outside valid ASCII range"}; + return static_cast(x); + } +}; + +template +struct NumericConvertVisitor : public boost::static_visitor +{ + // only valid for integral types + DesiredType operator()(const int8_t& x) const { return boost::numeric_cast(x); } + DesiredType operator()(const uint8_t& x) const { return boost::numeric_cast(x); } + DesiredType operator()(const int16_t& x) const { return boost::numeric_cast(x); } + DesiredType operator()(const uint16_t& x) const { return boost::numeric_cast(x); } + DesiredType operator()(const int32_t& x) const { return boost::numeric_cast(x); } + DesiredType operator()(const uint32_t& x) const { return boost::numeric_cast(x); } + + // anything else always throws + template + DesiredType operator()(const T& t) const + { + const std::string from = typeid(t).name(); + const std::string to = typeid(DesiredType).name(); + const std::string msg = "Tag: cannot convert type " + from + " to " + to; + throw std::runtime_error(msg); + return 0; + } +}; + +using ToInt8ConvertVisitor = NumericConvertVisitor; +using ToUInt8ConvertVisitor = NumericConvertVisitor; +using ToInt16ConvertVisitor = NumericConvertVisitor; +using ToUInt16ConvertVisitor = NumericConvertVisitor; +using ToInt32ConvertVisitor = NumericConvertVisitor; +using ToUInt32ConvertVisitor = NumericConvertVisitor; + +struct IsEqualVisitor : public boost::static_visitor +{ + template + bool operator()(const T&, const U&) const + { + // maybe allow conversions down the road? + // but for now, just fail if types are different + return false; + } + + bool operator()(const boost::blank&, const boost::blank&) const { return true; } + + template + bool operator()(const T& lhs, const T& rhs) const + { + return lhs == rhs; + } +}; + +struct TypenameVisitor : public boost::static_visitor +{ + std::string operator()(const boost::blank&) const { return "none"; } + std::string operator()(const int8_t&) const { return "int8_t"; } + std::string operator()(const uint8_t&) const { return "uint8_t"; } + std::string operator()(const int16_t&) const { return "int16_t"; } + std::string operator()(const uint16_t&) const { return "uint16_t"; } + std::string operator()(const int32_t&) const { return "int32_t"; } + std::string operator()(const uint32_t&) const { return "uint32_t"; } + std::string operator()(const float&) const { return "float"; } + std::string operator()(const std::string&) const { return "string"; } + std::string operator()(const std::vector&) const { return "vector"; } + std::string operator()(const std::vector&) const { return "vector"; } + std::string operator()(const std::vector&) const { return "vector"; } + std::string operator()(const std::vector&) const { return "vector"; } + std::string operator()(const std::vector&) const { return "vector"; } + std::string operator()(const std::vector&) const { return "vector"; } + std::string operator()(const std::vector&) const { return "vector"; } +}; + +} // anonymous + +static_assert(std::is_copy_constructible::value, "Tag(const Tag&) is not = default"); +static_assert(std::is_copy_assignable::value, "Tag& operator=(const Tag&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, "Tag(Tag&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +Tag::Tag(int8_t value) : data_{value} {} +Tag::Tag(uint8_t value) : data_{value} {} +Tag::Tag(int16_t value) : data_{value} {} +Tag::Tag(uint16_t value) : data_{value} {} +Tag::Tag(int32_t value) : data_{value} {} +Tag::Tag(uint32_t value) : data_{value} {} +Tag::Tag(float value) : data_{value} {} +Tag::Tag(std::string value) : data_{std::move(value)} {} +Tag::Tag(std::vector value) : data_{std::move(value)} {} +Tag::Tag(std::vector value) : data_{std::move(value)} {} +Tag::Tag(std::vector value) : data_{std::move(value)} {} +Tag::Tag(std::vector value) : data_{std::move(value)} {} +Tag::Tag(std::vector value) : data_{std::move(value)} {} +Tag::Tag(std::vector value) : data_{std::move(value)} {} +Tag::Tag(std::vector value) : data_{std::move(value)} {} + +Tag::Tag(int8_t value, const TagModifier mod) : data_{value}, modifier_(mod) +{ + if (mod == TagModifier::HEX_STRING) + throw std::runtime_error{ + "Tag: HEX_STRING is not a valid tag modifier for int8_t data. " + "It is intended for string-type data only."}; +} + +Tag::Tag(std::string value, TagModifier mod) : data_{std::move(value)}, modifier_{mod} +{ + if (mod == TagModifier::ASCII_CHAR) + throw std::runtime_error{ + "Tag: ASCII_CHAR is not a valid tag modifier for string-type data. " + "To construct an ASCII char tag, use a single-quoted value (e.g. 'X' instead of " + "\"X\")"}; +} + +Tag& Tag::operator=(boost::blank value) +{ + data_ = value; + return *this; +} + +Tag& Tag::operator=(int8_t value) +{ + data_ = value; + return *this; +} + +Tag& Tag::operator=(uint8_t value) +{ + data_ = value; + return *this; +} + +Tag& Tag::operator=(int16_t value) +{ + data_ = value; + return *this; +} + +Tag& Tag::operator=(uint16_t value) +{ + data_ = value; + return *this; +} + +Tag& Tag::operator=(int32_t value) +{ + data_ = value; + return *this; +} + +Tag& Tag::operator=(uint32_t value) +{ + data_ = value; + return *this; +} + +Tag& Tag::operator=(float value) +{ + data_ = value; + return *this; +} + +Tag& Tag::operator=(std::string value) +{ + data_ = std::move(value); + return *this; +} + +Tag& Tag::operator=(std::vector value) +{ + data_ = std::move(value); + return *this; +} + +Tag& Tag::operator=(std::vector value) +{ + data_ = std::move(value); + return *this; +} + +Tag& Tag::operator=(std::vector value) +{ + data_ = std::move(value); + return *this; +} + +Tag& Tag::operator=(std::vector value) +{ + data_ = std::move(value); + return *this; +} + +Tag& Tag::operator=(std::vector value) +{ + data_ = std::move(value); + return *this; +} + +Tag& Tag::operator=(std::vector value) +{ + data_ = std::move(value); + return *this; +} + +Tag& Tag::operator=(std::vector value) +{ + data_ = std::move(value); + return *this; +} + +bool Tag::operator==(const Tag& other) const +{ + return boost::apply_visitor(IsEqualVisitor(), data_, other.data_) && + (modifier_ == other.modifier_); +} + +bool Tag::operator!=(const Tag& other) const { return !(*this == other); } + +bool Tag::HasModifier(const TagModifier m) const +{ + // we just allow one at a time (for now at least) + return modifier_ == m; +} + +bool Tag::IsNull() const { return Type() == TagDataType::INVALID; } + +bool Tag::IsInt8() const { return Type() == TagDataType::INT8; } + +bool Tag::IsUInt8() const { return Type() == TagDataType::UINT8; } + +bool Tag::IsInt16() const { return Type() == TagDataType::INT16; } + +bool Tag::IsUInt16() const { return Type() == TagDataType::UINT16; } + +bool Tag::IsInt32() const { return Type() == TagDataType::INT32; } + +bool Tag::IsUInt32() const { return Type() == TagDataType::UINT32; } + +bool Tag::IsFloat() const { return Type() == TagDataType::FLOAT; } + +bool Tag::IsString() const { return Type() == TagDataType::STRING; } + +bool Tag::IsHexString() const { return IsString() && modifier_ == TagModifier::HEX_STRING; } + +bool Tag::IsInt8Array() const { return Type() == TagDataType::INT8_ARRAY; } + +bool Tag::IsUInt8Array() const { return Type() == TagDataType::UINT8_ARRAY; } + +bool Tag::IsInt16Array() const { return Type() == TagDataType::INT16_ARRAY; } + +bool Tag::IsUInt16Array() const { return Type() == TagDataType::UINT16_ARRAY; } + +bool Tag::IsInt32Array() const { return Type() == TagDataType::INT32_ARRAY; } + +bool Tag::IsUInt32Array() const { return Type() == TagDataType::UINT32_ARRAY; } + +bool Tag::IsFloatArray() const { return Type() == TagDataType::FLOAT_ARRAY; } + +bool Tag::IsSignedInt() const { return IsInt8() || IsInt16() || IsInt32(); } + +bool Tag::IsUnsignedInt() const { return IsUInt8() || IsUInt16() || IsUInt32(); } + +bool Tag::IsIntegral() const { return IsSignedInt() || IsUnsignedInt(); } + +bool Tag::IsNumeric() const { return IsIntegral() || IsFloat(); } + +bool Tag::IsSignedArray() const { return IsInt8Array() || IsInt16Array() || IsInt32Array(); } + +bool Tag::IsUnsignedArray() const { return IsUInt8Array() || IsUInt16Array() || IsUInt32Array(); } + +bool Tag::IsIntegralArray() const { return IsSignedArray() || IsUnsignedArray(); } + +bool Tag::IsArray() const { return IsIntegralArray() || IsFloatArray(); } + +TagModifier Tag::Modifier() const { return modifier_; } + +Tag& Tag::Modifier(const TagModifier m) +{ + modifier_ = m; + return *this; +} + +char Tag::ToAscii() const { return boost::apply_visitor(AsciiConvertVisitor(), data_); } + +int8_t Tag::ToInt8() const +{ + if (IsInt8()) return boost::get(data_); + return boost::apply_visitor(ToInt8ConvertVisitor(), data_); +} + +uint8_t Tag::ToUInt8() const +{ + if (IsUInt8()) return boost::get(data_); + return boost::apply_visitor(ToUInt8ConvertVisitor(), data_); +} + +int16_t Tag::ToInt16() const +{ + if (IsInt16()) return boost::get(data_); + return boost::apply_visitor(ToInt16ConvertVisitor(), data_); +} + +uint16_t Tag::ToUInt16() const +{ + if (IsUInt16()) return boost::get(data_); + return boost::apply_visitor(ToUInt16ConvertVisitor(), data_); +} + +int32_t Tag::ToInt32() const +{ + if (IsInt32()) return boost::get(data_); + return boost::apply_visitor(ToInt32ConvertVisitor(), data_); +} + +uint32_t Tag::ToUInt32() const +{ + if (IsUInt32()) return boost::get(data_); + return boost::apply_visitor(ToUInt32ConvertVisitor(), data_); +} + +float Tag::ToFloat() const { return boost::get(data_); } + +std::string Tag::ToString() const { return boost::get(data_); } + +std::vector Tag::ToInt8Array() const { return boost::get >(data_); } + +std::vector Tag::ToUInt8Array() const { return boost::get >(data_); } + +std::vector Tag::ToInt16Array() const { return boost::get >(data_); } + +std::vector Tag::ToUInt16Array() const +{ + return boost::get >(data_); +} + +std::vector Tag::ToInt32Array() const { return boost::get >(data_); } + +std::vector Tag::ToUInt32Array() const +{ + return boost::get >(data_); +} + +std::vector Tag::ToFloatArray() const { return boost::get >(data_); } + +TagDataType Tag::Type() const { return TagDataType(data_.which()); } + +std::string Tag::Typename() const { return boost::apply_visitor(TypenameVisitor(), data_); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/TagCollection.cpp b/src/TagCollection.cpp new file mode 100644 index 0000000..feab76d --- /dev/null +++ b/src/TagCollection.cpp @@ -0,0 +1,17 @@ +// File Description +/// \file TagCollection.cpp +/// \brief Implements the TagCollection class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/TagCollection.h" + +namespace PacBio { +namespace BAM { + +bool TagCollection::Contains(const std::string& name) const { return count(name) != 0; } + +} // namespace BAM +} // namespace PacBio diff --git a/src/TextFileReader.cpp b/src/TextFileReader.cpp new file mode 100644 index 0000000..fa76e66 --- /dev/null +++ b/src/TextFileReader.cpp @@ -0,0 +1,115 @@ +// File Description +/// \file TextFileReader.cpp +/// \brief Implements the TextFileReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/TextFileReader.h" + +#include + +#include +#include + +#include +#include + +#include "MemoryUtils.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "TextFileReader(const TextFileReader&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "TextFileReader& operator=(const TextFileReader&) is not = delete"); + +class TextFileReader::TextFileReaderPrivate +{ +public: + TextFileReaderPrivate(std::string filename) : filename_{std::move(filename)}, k_{0, 0, nullptr} + { + // "ru" : read & supply plain output + bgzf_.reset(bgzf_open(filename_.c_str(), "ru")); + if (bgzf_.get() == nullptr) + throw std::runtime_error("TextFileReader - could not open zipped file: " + filename_ + + " for reading"); + + // pre-fetch first line + GetNext(); + } + + ~TextFileReaderPrivate() { free(k_.s); } + + void GetNext() + { + line_.clear(); + + // be sure we skip empty lines + while (line_.empty()) { + const int result = bgzf_getline(bgzf_.get(), '\n', &k_); + + // found data + if (result > 0) { + line_ = std::string{k_.s, k_.l}; + return; + } + + // empty line, try again + else if (result == 0) + continue; + + // EOF (no error, but will stop next TextFileReader iteration + else if (result == -1) + return; + + // else error + else { + throw std::runtime_error("TextFileReader - could not read from text file: " + + filename_ + "\nreason: htslib error code " + + std::to_string(result)); + } + } + } + + std::string filename_; + std::string line_; + std::unique_ptr bgzf_; // can handle plain text or gzipped + kstring_t k_; +}; + +TextFileReader::TextFileReader(std::string filename) + : PacBio::BAM::internal::QueryBase{} + , d_{std::make_unique(std::move(filename))} +{ +} + +TextFileReader::TextFileReader(TextFileReader&&) noexcept = default; + +TextFileReader& TextFileReader::operator=(TextFileReader&&) noexcept = default; + +TextFileReader::~TextFileReader() = default; + +bool TextFileReader::GetNext(std::string& line) +{ + if (d_->line_.empty()) return false; + + line = d_->line_; + d_->GetNext(); + return true; +} + +std::vector TextFileReader::ReadAll(const std::string& fn) +{ + std::vector result; + result.reserve(256); + TextFileReader reader{fn}; + for (const auto& seq : reader) + result.emplace_back(seq); + return result; +} + +} // namespace BAM +} // namespace PacBio \ No newline at end of file diff --git a/src/TextFileWriter.cpp b/src/TextFileWriter.cpp new file mode 100644 index 0000000..7c97432 --- /dev/null +++ b/src/TextFileWriter.cpp @@ -0,0 +1,88 @@ + +// File Description +/// \file TextFileWriter.cpp +/// \brief Implements the TextFileWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/TextFileWriter.h" + +#include + +#include +#include +#include + +#include + +#include "FileProducer.h" +#include "MemoryUtils.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "TextFileWriter(const TextFileWriter&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "TextFileWriter& operator=(const TextFileWriter&) is not = delete"); + +class TextFileWriter::TextFileWriterPrivate : public FileProducer +{ +public: + TextFileWriterPrivate(const std::string& filename) : FileProducer{filename} + { + isZipped_ = boost::algorithm::iends_with(filename, ".gz"); + + if (isZipped_) { + // open for gzipped text + bgzf_.reset(bgzf_open(TempFilename().c_str(), "wg")); + if (bgzf_.get() == nullptr) { + throw std::runtime_error("TextFileWriter - could not open file: " + filename + + " for writing"); + } + } else { + // open for plain text + out_.open(TempFilename()); + if (!out_) { + throw std::runtime_error("TextFileWriter - could not open file: " + filename + + " for writing"); + } + } + } + + void Write(const std::string& line) + { + if (isZipped_) { + const size_t length = line.size(); + ssize_t written = bgzf_write(bgzf_.get(), line.c_str(), length); + written += bgzf_write(bgzf_.get(), "\n", 1); + if (written != static_cast(length + 1)) + throw std::runtime_error("TextFileWriter - error writing to file: " + + TargetFilename()); + } else { + out_ << line << '\n'; + } + } + + bool isZipped_ = false; + std::unique_ptr bgzf_; + std::ofstream out_; +}; + +TextFileWriter::TextFileWriter(const std::string& filename) + : d_{std::make_unique(filename)} +{ +} + +TextFileWriter::TextFileWriter(TextFileWriter&&) noexcept = default; + +TextFileWriter& TextFileWriter::operator=(TextFileWriter&&) noexcept = default; + +TextFileWriter::~TextFileWriter() = default; + +void TextFileWriter::Write(const std::string& line) { d_->Write(line); } + +} // namespace BAM +} // namespace PacBio \ No newline at end of file diff --git a/src/TimeUtils.h b/src/TimeUtils.h new file mode 100644 index 0000000..270afd5 --- /dev/null +++ b/src/TimeUtils.h @@ -0,0 +1,73 @@ +// Author: Derek Barnett + +#ifndef TIMEUTILS_H +#define TIMEUTILS_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +class TimeUtils +{ +public: + static std::string ToIso8601(const std::chrono::system_clock::time_point& tp) + { + // get time info + const time_t ttime_t = std::chrono::system_clock::to_time_t(tp); + const std::chrono::system_clock::time_point tp_sec = + std::chrono::system_clock::from_time_t(ttime_t); + const std::chrono::milliseconds ms = + std::chrono::duration_cast(tp - tp_sec); + const std::tm* ttm = + gmtime(&ttime_t); // static obj, no free needed (may not be thread-safe though) + + // format output + constexpr static const char date_time_format[] = "%FT%T"; + char date_time_str[50]; + strftime(date_time_str, sizeof(date_time_str), date_time_format, ttm); + std::string result(date_time_str); + if (ms.count() > 0) { + result.append("."); + result.append(std::to_string(ms.count())); + } + result.append("Z"); + return result; + } + + static std::string ToDataSetFormat(const std::chrono::system_clock::time_point& tp) + { + // get time info + const time_t ttime_t = std::chrono::system_clock::to_time_t(tp); + const std::chrono::system_clock::time_point tp_sec = + std::chrono::system_clock::from_time_t(ttime_t); + const std::chrono::milliseconds ms = + std::chrono::duration_cast(tp - tp_sec); + const std::tm* ttm = + gmtime(&ttime_t); // static obj, no free needed (may not be thread-safe though) + + // format output + constexpr static const char date_time_format[] = "%y%m%d_%H%M%S"; + char date_time_str[50]; + strftime(date_time_str, sizeof(date_time_str), date_time_format, ttm); + std::string result(date_time_str); + if (ms.count() > 0) result.append(std::to_string(ms.count())); + return result; + } + + static std::chrono::system_clock::time_point CurrentTime() + { + return std::chrono::system_clock::now(); + } +}; + +} // namespace BAM +} // namespace PacBio + +#endif // TIMEUTILS_H diff --git a/src/ValidationErrors.cpp b/src/ValidationErrors.cpp new file mode 100644 index 0000000..5e88885 --- /dev/null +++ b/src/ValidationErrors.cpp @@ -0,0 +1,74 @@ +// File Description +/// \file ValidationErrors.cpp +/// \brief Implements the ValidationErrors class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/exception/ValidationException.h" + +#include +#include + +#include "ValidationErrors.h" +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { + +const size_t ValidationErrors::MAX; + +ValidationErrors::ValidationErrors(const size_t maxNumErrors) + : maxNumErrors_{maxNumErrors}, currentNumErrors_{0} +{ + if (maxNumErrors_ == 0) maxNumErrors_ = ValidationErrors::MAX; +} + +void ValidationErrors::AddFileError(const std::string& fn, std::string details) +{ + fileErrors_[fn].push_back(std::move(details)); + OnErrorAdded(); +} + +void ValidationErrors::AddReadGroupError(const std::string& rg, std::string details) +{ + readGroupErrors_[rg].push_back(std::move(details)); + OnErrorAdded(); +} + +void ValidationErrors::AddRecordError(const std::string& name, std::string details) +{ + recordErrors_[name].push_back(std::move(details)); + OnErrorAdded(); +} + +void ValidationErrors::AddTagLengthError(const std::string& name, const std::string& tagLabel, + const std::string& tagName, const size_t observed, + const size_t expected) +{ + // format + std::ostringstream s; + s << tagLabel << " tag (" << tagName << ") length: " << observed + << ", does not match expected length: " << expected; + AddRecordError(name, s.str()); +} + +bool ValidationErrors::IsEmpty() const { return currentNumErrors_ == 0; } + +size_t ValidationErrors::MaxNumErrors() const { return maxNumErrors_; } + +void ValidationErrors::OnErrorAdded() +{ + ++currentNumErrors_; + if (currentNumErrors_ == maxNumErrors_) ThrowErrors(); +} + +void ValidationErrors::ThrowErrors() +{ + throw ValidationException{std::move(fileErrors_), std::move(readGroupErrors_), + std::move(recordErrors_)}; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/ValidationErrors.h b/src/ValidationErrors.h new file mode 100644 index 0000000..2700196 --- /dev/null +++ b/src/ValidationErrors.h @@ -0,0 +1,65 @@ +// File Description +/// \file ValidationErrors.h +/// \brief Defines the ValidationErrors class. +// +// Author: Derek Barnett + +#ifndef VALIDATIONERRORS_H +#define VALIDATIONERRORS_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +/// The ValidationErrors class catches error messages accumulated during +/// validation (see Validator). +/// +/// Convenience methods are provided for different BAM components, to help +/// format the displayed output. +/// +/// A maximum number of errors can be provided at construction, and this class +/// will automatially throw a ValidationException whenever that count is reached. +/// Otherwise, the Validator will check IsEmpty() and call ThrowErrors() if true. +/// +class ValidationErrors +{ +public: + typedef std::vector ErrorList; + typedef std::map ErrorMap; + + static const size_t MAX = std::numeric_limits::max(); + + explicit ValidationErrors(const size_t maxNumErrors = ValidationErrors::MAX); + + void AddFileError(const std::string& fn, std::string details); + void AddReadGroupError(const std::string& rg, std::string details); + void AddRecordError(const std::string& name, std::string details); + void AddTagLengthError(const std::string& name, const std::string& tagLabel, + const std::string& tagName, const size_t observed, + const size_t expected); + + bool IsEmpty() const; + size_t MaxNumErrors() const; + void ThrowErrors(); + +private: + size_t maxNumErrors_; + size_t currentNumErrors_; + ErrorMap fileErrors_; + ErrorMap readGroupErrors_; + ErrorMap recordErrors_; + + void OnErrorAdded(); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // VALIDATIONERRORS_H diff --git a/src/ValidationException.cpp b/src/ValidationException.cpp new file mode 100644 index 0000000..99bcfd1 --- /dev/null +++ b/src/ValidationException.cpp @@ -0,0 +1,74 @@ +// File Description +/// \file ValidationException.cpp +/// \brief Implements the ValidationException class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/exception/ValidationException.h" + +namespace PacBio { +namespace BAM { + +ValidationException::ValidationException(ErrorMap fileErrors, ErrorMap readGroupErrors, + ErrorMap recordErrors) + : std::runtime_error{""} + , fileErrors_{std::move(fileErrors)} + , readGroupErrors_{std::move(readGroupErrors)} + , recordErrors_{std::move(recordErrors)} +{ + FormatMessage(); +} + +const ValidationException::ErrorMap& ValidationException::FileErrors() const { return fileErrors_; } + +const ValidationException::ErrorMap& ValidationException::ReadGroupErrors() const +{ + return readGroupErrors_; +} + +const ValidationException::ErrorMap& ValidationException::RecordErrors() const +{ + return recordErrors_; +} + +const char* ValidationException::what() const noexcept { return msg_.c_str(); } + +void ValidationException::FormatMessage() +{ + std::ostringstream s; + s << "Validation failed:\n"; + + // file errors + if (!fileErrors_.empty()) { + for (const auto& fileError : fileErrors_) { + s << " In file (" << fileError.first << ") : \n"; + for (const auto& e : fileError.second) + s << " " << e << '\n'; + } + } + + // read group errors + if (!readGroupErrors_.empty()) { + for (const auto& rgError : readGroupErrors_) { + s << " In read group (" << rgError.first << ") :\n"; + for (const auto& e : rgError.second) + s << " " << e << '\n'; + } + } + + // record errors + if (!recordErrors_.empty()) { + for (const auto& recordError : readGroupErrors_) { + s << " In record (" << recordError.first << ") : \n"; + for (const auto& e : recordError.second) + s << " " << e << '\n'; + } + } + + msg_ = s.str(); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/Validator.cpp b/src/Validator.cpp new file mode 100644 index 0000000..be638dc --- /dev/null +++ b/src/Validator.cpp @@ -0,0 +1,406 @@ +// File Description +/// \file Validator.cpp +/// \brief Implements the Validator class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/Validator.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ValidationErrors.h" +#include "Version.h" +#include "pbbam/BamFile.h" +#include "pbbam/BamHeader.h" +#include "pbbam/BamRecord.h" +#include "pbbam/EntireFileQuery.h" +#include "pbbam/ReadGroupInfo.h" + +namespace PacBio { +namespace BAM { +namespace { + +struct ilexcompare_wrapper +{ + bool operator()(const std::string& lhs, const std::string& rhs) const + { + return boost::ilexicographical_compare(lhs, rhs); + } +}; + +// clang-format off +static const std::set AcceptedSortOrders +{ + "unknown", + "unsorted", + "queryname", + "coordinate" +}; + +static const std::set AcceptedReadTypes +{ + "POLYMERASE", + "HQREGION", + "SUBREAD", + "CCS", + "SCRAP", + "UNKNOWN" +}; +// clang-format on + +static void ValidateReadGroup(const ReadGroupInfo& rg, std::unique_ptr& errors) +{ + const std::string id = rg.Id(); + + // has required fields + if (id.empty()) errors->AddReadGroupError(id, "missing ID"); + if (rg.MovieName().empty()) errors->AddReadGroupError(id, "missing movie name (PU tag)"); + // 3.0.2 adds required RG:PM - do not check for now, we'll add version-aware + // validation down the road + + // description tag has required components + if (rg.ReadType().empty()) errors->AddReadGroupError(id, "missing READTYPE in description"); + if (rg.BindingKit().empty()) errors->AddReadGroupError(id, "missing BINDINGKIT in description"); + if (rg.SequencingKit().empty()) + errors->AddReadGroupError(id, "missing SEQUENCINGKIT in description"); + if (rg.BasecallerVersion().empty()) + errors->AddReadGroupError(id, "missing BASECALLERVERSION in description"); + if (rg.FrameRateHz().empty()) + errors->AddReadGroupError(id, "missing FRAMERATEHZ in description"); + + // stored ID matches expected ID (as calculated from movie & type) + if (!id.empty()) { + const auto expectedId = MakeReadGroupId(rg.MovieName(), rg.ReadType()); + if (expectedId != id) { + const std::string msg{"stored ID: " + id + " does not match computed ID: " + + expectedId}; + errors->AddReadGroupError(id, std::move(msg)); + } + } + + // valid read type + if (!rg.ReadType().empty()) { + if (AcceptedReadTypes.find(rg.ReadType()) == AcceptedReadTypes.cend()) + errors->AddReadGroupError(id, "read type: " + rg.ReadType() + " is unknown"); + } + + // valid read chemistry (binding, sequencing, chemistry) + if (!rg.BindingKit().empty() && !rg.SequencingKit().empty() && + !rg.BasecallerVersion().empty()) { + try { + auto chem = rg.SequencingChemistry(); + boost::ignore_unused(chem); + } catch (std::exception& e) { + errors->AddReadGroupError(id, e.what()); + } + } + + // frame rate convertable to floating point + if (!rg.FrameRateHz().empty()) { + try { + const float frameRate = std::stof(rg.FrameRateHz()); + boost::ignore_unused(frameRate); + } catch (std::exception& e) { + errors->AddReadGroupError(id, e.what()); + } + } +} + +static void ValidateHeader(const BamHeader& header, const std::string& filename, + std::unique_ptr& errors) +{ + const std::string& fn = filename; + + // SAM/BAM version + try { + Version v(header.Version()); + boost::ignore_unused(v); + } catch (std::exception& e) { + errors->AddFileError(fn, std::string{"SAM version (@HD:VN) failed: "} + e.what()); + } + + // sort order + const std::string sortOrder = header.SortOrder(); + if (AcceptedSortOrders.find(sortOrder) == AcceptedSortOrders.end()) + errors->AddFileError(fn, std::string{"unknown sort order: "} + sortOrder); + + // PacBio version + try { + const Version v{header.PacBioBamVersion()}; + const Version minimum{3, 0, 1}; + if (v < minimum) { + + std::string msg{"PacBioBAM version (@HD:pb) "}; + msg += v.ToString(); + msg += " is older than the minimum supported version (" + minimum.ToString() + ")"; + errors->AddFileError(fn, std::move(msg)); + } + } catch (std::exception& e) { + errors->AddFileError( + fn, std::string{"PacBioBAM version (@HD:pb) failed to parse: "} + e.what()); + } + + // sequences? + + // read groups + for (const ReadGroupInfo& rg : header.ReadGroups()) + ValidateReadGroup(rg, errors); +} + +static void ValidateMetadata(const BamFile& file, std::unique_ptr& errors) +{ + // filename + const std::string fn{file.Filename()}; + if (fn == "-") { + errors->AddFileError(fn, + "validation not is available for streamed BAM. Please " + "write to a file and run validation on it."); + errors->ThrowErrors(); // quit early + } + if (boost::algorithm::ends_with(fn, ".bam") || boost::algorithm::ends_with(fn, ".bam.tmp")) { + errors->AddFileError(fn, "non-standard file extension"); + } + + // EOF + if (!file.HasEOF()) errors->AddFileError(fn, "missing end-of-file marker"); + + // has PBI + if (!file.PacBioIndexExists()) errors->AddFileError(fn, "missing PBI file"); + + // header + ValidateHeader(file.Header(), file.Filename(), errors); +} + +void ValidateMappedRecord(const BamRecord& b, std::unique_ptr& errors) +{ + const std::string name{b.FullName()}; + if (b.ReferenceStart() < 0) errors->AddRecordError(name, "mapped record position is invalid"); + if (b.ReferenceId() < 0) errors->AddRecordError(name, "mapped record reference ID is invalid"); + + // what else?? +} + +void ValidateRecordCore(const BamRecord& b, std::unique_ptr& errors) +{ + if (!IsCcsOrTranscript(b.Type())) { + const auto qStart = b.QueryStart(); + const auto qEnd = b.QueryEnd(); + if (qStart >= qEnd) { + errors->AddRecordError(b.FullName(), "queryStart (qs) should be < queryEnd (qe)"); + } + } +} + +void ValidateRecordReadGroup(const BamRecord& b, std::unique_ptr& errors) +{ + try { + auto rg = b.ReadGroup(); + boost::ignore_unused(rg); + } catch (std::exception& e) { + errors->AddRecordError(b.FullName(), e.what()); + } +} + +void ValidateRecordRequiredTags(const BamRecord& b, std::unique_ptr& errors) +{ + const auto name = b.FullName(); + const auto isCcsOrTranscript = IsCcsOrTranscript(b.Type()); + if (!isCcsOrTranscript) { + // qe/qs + const bool hasQueryStart = b.HasQueryStart(); + const bool hasQueryEnd = b.HasQueryEnd(); + if (hasQueryStart && hasQueryEnd) { + const auto qStart = b.QueryStart(); + const auto qEnd = b.QueryEnd(); + if (qStart >= qEnd) + errors->AddRecordError(name, "queryStart (qs) should be < queryEnd (qe)"); + } else { + if (!hasQueryStart) errors->AddRecordError(name, "missing tag: qs (queryStart)"); + if (!hasQueryEnd) errors->AddRecordError(name, "missing tag: qe (queryEnd)"); + } + } + + // zm + if (!b.HasHoleNumber()) errors->AddRecordError(name, "missing tag: zm (ZMW hole number)"); + + // np + if (!b.HasNumPasses()) + errors->AddRecordError(name, "missing tag: np (num passes)"); + else { + const auto numPasses = b.NumPasses(); + if (!isCcsOrTranscript && numPasses != 1) + errors->AddRecordError(name, "np (numPasses) tag for non-CCS records should be 1"); + } + + // rq + if (!b.HasReadAccuracy()) errors->AddRecordError(name, "missing tag: rq (read accuracy)"); + + // sn + if (!b.HasSignalToNoise()) + errors->AddRecordError(name, "missing tag: sn (signal-to-noise ratio)"); +} + +void ValidateRecordTagLengths(const BamRecord& b, std::unique_ptr& errors) +{ + const auto name = b.FullName(); + const size_t expectedLength = + (IsCcsOrTranscript(b.Type()) ? b.Sequence().size() : (b.QueryEnd() - b.QueryStart())); + + // check "per-base"-type data lengths are compatible + if (b.Sequence().size() != expectedLength) + errors->AddRecordError(name, "sequence length does not match expected length"); + + if (b.HasDeletionQV()) { + if (b.DeletionQV().size() != expectedLength) + errors->AddTagLengthError(name, "DeletionQV", "dq", b.DeletionQV().size(), + expectedLength); + } + if (b.HasDeletionTag()) { + if (b.DeletionTag().size() != expectedLength) + errors->AddTagLengthError(name, "DeletionTag", "dt", b.DeletionTag().size(), + expectedLength); + } + if (b.HasInsertionQV()) { + if (b.InsertionQV().size() != expectedLength) + errors->AddTagLengthError(name, "InsertionQV", "iq", b.InsertionQV().size(), + expectedLength); + } + if (b.HasMergeQV()) { + if (b.MergeQV().size() != expectedLength) + errors->AddTagLengthError(name, "MergeQV", "mq", b.MergeQV().size(), expectedLength); + } + if (b.HasSubstitutionQV()) { + if (b.SubstitutionQV().size() != expectedLength) + errors->AddTagLengthError(name, "SubstitutionQV", "sq", b.SubstitutionQV().size(), + expectedLength); + } + if (b.HasSubstitutionTag()) { + if (b.SubstitutionTag().size() != expectedLength) + errors->AddTagLengthError(name, "SubstitutionTag", "st", b.SubstitutionTag().size(), + expectedLength); + } + if (b.HasIPD()) { + if (b.IPD().size() != expectedLength) + errors->AddTagLengthError(name, "IPD", "ip", b.IPD().size(), expectedLength); + } + + // NOTE: disabling "internal" tag checks for now, only production tags +} + +void ValidateUnmappedRecord(const BamRecord& b, std::unique_ptr& errors) +{ + const std::string name{b.FullName()}; + if (b.ReferenceStart() != -1) errors->AddRecordError(name, "unmapped record has a position"); + if (b.ReferenceId() != -1) errors->AddRecordError(name, "unmapped record has a reference ID"); +} + +static void ValidateRecord(const BamRecord& b, std::unique_ptr& errors) +{ + ValidateRecordCore(b, errors); + ValidateRecordReadGroup(b, errors); + ValidateRecordRequiredTags(b, errors); + ValidateRecordTagLengths(b, errors); + if (b.IsMapped()) + ValidateMappedRecord(b, errors); + else + ValidateUnmappedRecord(b, errors); +} + +} // namespace + +bool Validator::IsValid(const BamFile& file, const bool entireFile) +{ + try { + if (entireFile) + ValidateEntireFile(file, 1); + else + ValidateFileMetadata(file, 1); + return true; + } catch (std::exception&) { + return false; + } +} + +bool Validator::IsValid(const BamHeader& header) +{ + try { + Validate(header, 1); + return true; + } catch (std::exception&) { + return false; + } +} + +bool Validator::IsValid(const BamRecord& record) +{ + try { + Validate(record, 1); + return true; + } catch (std::exception&) { + return false; + } +} + +bool Validator::IsValid(const ReadGroupInfo& rg) +{ + try { + Validate(rg, 1); + return true; + } catch (std::exception&) { + return false; + } +} + +void Validator::Validate(const BamHeader& header, const size_t maxErrors) +{ + auto errors = std::make_unique(maxErrors); + ValidateHeader(header, "unknown", errors); + if (!errors->IsEmpty()) errors->ThrowErrors(); +} + +void Validator::Validate(const ReadGroupInfo& rg, const size_t maxErrors) +{ + auto errors = std::make_unique(maxErrors); + ValidateReadGroup(rg, errors); + if (!errors->IsEmpty()) errors->ThrowErrors(); +} + +void Validator::Validate(const BamRecord& b, const size_t maxErrors) +{ + auto errors = std::make_unique(maxErrors); + ValidateRecord(b, errors); + if (!errors->IsEmpty()) errors->ThrowErrors(); +} + +void Validator::ValidateEntireFile(const BamFile& file, const size_t maxErrors) +{ + auto errors = std::make_unique(maxErrors); + ValidateMetadata(file, errors); + + EntireFileQuery query(file); + for (const BamRecord& record : query) + ValidateRecord(record, errors); + + if (!errors->IsEmpty()) errors->ThrowErrors(); +} + +void Validator::ValidateFileMetadata(const BamFile& file, const size_t maxErrors) +{ + auto errors = std::make_unique(maxErrors); + ValidateMetadata(file, errors); + if (!errors->IsEmpty()) errors->ThrowErrors(); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/Version.cpp b/src/Version.cpp new file mode 100644 index 0000000..c1af408 --- /dev/null +++ b/src/Version.cpp @@ -0,0 +1,51 @@ +// File Description +/// \file Version.cpp +/// \brief Implements the Version class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "Version.h" + +#include +#include + +#include "pbbam/StringUtilities.h" + +namespace PacBio { +namespace BAM { + +const Version Version::Current = Version(3, 0, 7); +const Version Version::Minimum = Version(3, 0, 1); + +// string must be ".." +Version::Version(const std::string& v) : major_{0}, minor_{0}, revision_{0} +{ + // parse string + try { + const auto fields = Split(v, '.'); + const auto numFields = fields.size(); + if (numFields == 0) throw std::runtime_error{"Version: empty string"}; + major_ = std::stoi(fields.at(0)); + if (numFields > 1) { + minor_ = std::stoi(fields.at(1)); + if (numFields > 2) revision_ = std::stoi(fields.at(2)); + } + } catch (std::exception&) { + throw std::runtime_error{"Version: could not parse: " + v}; + } + + // ensure valid numbers + Check(); +} + +std::string Version::ToString() const +{ + std::ostringstream s; + s << major_ << '.' << minor_ << '.' << revision_; + return s.str(); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/Version.h b/src/Version.h new file mode 100644 index 0000000..278259e --- /dev/null +++ b/src/Version.h @@ -0,0 +1,134 @@ +// File Description +/// \file Version.h +/// \brief Defines the Version class. +// +// Author: Derek Barnett + +#ifndef PACBIOBAM_VERSION_H +#define PACBIOBAM_VERSION_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +class Version +{ +public: + static const Version Current; + static const Version Minimum; + + constexpr Version() = default; + + Version(int major, int minor, int revision); + + // string must be ".." + explicit Version(const std::string& v); + + Version(const Version&) = default; + Version(Version&&) noexcept = default; + Version& operator=(const Version&) = default; + Version& operator=(Version&&) noexcept = default; + ~Version() = default; + + bool operator==(const Version& other) const; + bool operator!=(const Version& other) const; + bool operator<(const Version& other) const; + bool operator<=(const Version& other) const; + bool operator>(const Version& other) const; + bool operator>=(const Version& other) const; + + std::string ToString() const; + explicit operator std::string() const; + + int Major() const; + int Minor() const; + int Revision() const; + + Version& Major(int major); + Version& Minor(int minor); + Version& Revision(int revision); + +private: + void Check() const; + + int major_ = 0; + int minor_ = 0; + int revision_ = 0; +}; + +inline std::ostream& operator<<(std::ostream& out, const Version& version) +{ + out << version.ToString(); + return out; +} + +inline Version::Version(int major, int minor, int revision) + : major_{major}, minor_{minor}, revision_{revision} +{ + Check(); +} + +inline bool Version::operator==(const Version& other) const +{ + return std::tie(major_, minor_, revision_) == + std::tie(other.major_, other.minor_, other.revision_); +} + +inline bool Version::operator!=(const Version& other) const { return !(*this == other); } + +inline bool Version::operator<(const Version& other) const +{ + return std::tie(major_, minor_, revision_) < + std::tie(other.major_, other.minor_, other.revision_); +} +inline bool Version::operator<=(const Version& other) const { return !(*this > other); } + +inline bool Version::operator>(const Version& other) const { return other < *this; } + +inline bool Version::operator>=(const Version& other) const { return !(*this < other); } + +inline Version::operator std::string() const { return ToString(); } + +inline void Version::Check() const +{ + if (major_ < 0 || minor_ < 0 || revision_ < 0) + throw std::runtime_error{"version cannot contain negative numbers"}; +} + +inline int Version::Major() const { return major_; } + +inline Version& Version::Major(int major) +{ + major_ = major; + Check(); + return *this; +} + +inline int Version::Minor() const { return minor_; } + +inline Version& Version::Minor(int minor) +{ + minor_ = minor; + Check(); + return *this; +} + +inline int Version::Revision() const { return revision_; } + +inline Version& Version::Revision(int revision) +{ + revision_ = revision; + Check(); + return *this; +} + +} // namespace BAM +} // namespace PacBio + +#endif // PACBIOBAM_VERSION_H diff --git a/src/VirtualRegion.cpp b/src/VirtualRegion.cpp new file mode 100644 index 0000000..3a437ce --- /dev/null +++ b/src/VirtualRegion.cpp @@ -0,0 +1,53 @@ +// File Description +/// \file VirtualRegionTypeMap.cpp +/// \brief Implements the VirtualRegionTypeMap class. +// +// Author: Armin Töpfer + +#include "PbbamInternalConfig.h" + +#include +#include +#include + +#include "pbbam/virtual/VirtualRegion.h" + +namespace PacBio { +namespace BAM { + +static_assert(std::is_copy_constructible::value, + "VirtualRegion(const VirtualRegion&) is not = default"); +static_assert(std::is_copy_assignable::value, + "VirtualRegion& operator=(const VirtualRegion&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "VirtualRegion(VirtualRegion&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "VirtualRegion& operator=(VirtualRegion&&) is not = noexcept"); + +VirtualRegion::VirtualRegion(const VirtualRegionType type_, const int beginPos_, const int endPos_, + const int score_) + : type{type_}, beginPos{beginPos_}, endPos{endPos_}, cxTag{}, score{score_} +{ +} + +VirtualRegion::VirtualRegion(const VirtualRegionType type_, const int beginPos_, const int endPos_, + const LocalContextFlags cxTag_, const int barcodeLeft_, + const int barcodeRight_, const int score_) + : type{type_} + , beginPos{beginPos_} + , endPos{endPos_} + , cxTag{cxTag_} + , barcodeLeft{barcodeLeft_} + , barcodeRight{barcodeRight_} + , score{score_} +{ +} + +bool VirtualRegion::operator==(const VirtualRegion& v1) const +{ + return std::tie(type, beginPos, endPos) == std::tie(v1.type, v1.beginPos, v1.endPos); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/VirtualRegionTypeMap.cpp b/src/VirtualRegionTypeMap.cpp new file mode 100644 index 0000000..99c99db --- /dev/null +++ b/src/VirtualRegionTypeMap.cpp @@ -0,0 +1,22 @@ +// File Description +/// \file VirtualRegionTypeMap.cpp +/// \brief Implements the VirtualRegionTypeMap class. +// +// Author: Armin Töpfer + +#include "PbbamInternalConfig.h" + +#include "pbbam/virtual/VirtualRegionTypeMap.h" + +namespace PacBio { +namespace BAM { + +std::map VirtualRegionTypeMap::ParseChar{ + {'A', VirtualRegionType::ADAPTER}, + {'B', VirtualRegionType::BARCODE}, + {'H', VirtualRegionType::HQREGION}, + {'F', VirtualRegionType::FILTERED}, + {'L', VirtualRegionType::LQREGION}}; + +} // namespace BAM +} // namespace PacBio diff --git a/src/VirtualStitching.h b/src/VirtualStitching.h new file mode 100644 index 0000000..0f47002 --- /dev/null +++ b/src/VirtualStitching.h @@ -0,0 +1,70 @@ +// File Description +/// \file VirtualStitching.h +/// \brief Utilities for virtual ZMW stitiching. +// +// Author: Derek Barnett + +#ifndef VIRTUALSTITCHING_H +#define VIRTUALSTITCHING_H + +#include "pbbam/Config.h" + +#include +#include +#include + +#include + +#include + +namespace PacBio { +namespace BAM { + +using StitchingSources = std::deque>; + +inline boost::optional ScrapsFileId(const ExternalResource& resource) +{ + const auto& childResources = resource.ExternalResources(); + for (const auto& childResource : childResources) { + const auto& childMetatype = childResource.MetaType(); + if (childMetatype == "PacBio.SubreadFile.ScrapsBamFile" || + childMetatype == "PacBio.SubreadFile.HqScrapsBamFile") { + return childResource.ResourceId(); + } + } + return boost::none; +} + +inline StitchingSources SourcesFromDataset(const DataSet& dataset) +{ + StitchingSources sources; + + const ExternalResources& resources = dataset.ExternalResources(); + for (const ExternalResource& resource : resources) { + + boost::optional primaryId; + boost::optional scrapsId; + + // if resource is possible "primary" BAM, store & look for associated scraps + const auto& metatype = resource.MetaType(); + if (metatype == "PacBio.SubreadFile.SubreadBamFile" || + metatype == "PacBio.SubreadFile.HqRegionBamFile") { + primaryId = resource.ResourceId(); + scrapsId = ScrapsFileId(resource); + } + + // if found, resolve paths & store + if (primaryId && scrapsId) { + std::string primaryFn = dataset.ResolvePath(primaryId.get()); + std::string scrapsFn = dataset.ResolvePath(scrapsId.get()); + sources.emplace_back(std::make_pair(primaryFn, scrapsFn)); + } + } + + return sources; +} + +} // namespace BAM +} // namespace PacBio + +#endif // VIRTUALSTITCHING_H diff --git a/src/VirtualZmwBamRecord.cpp b/src/VirtualZmwBamRecord.cpp new file mode 100644 index 0000000..192e14f --- /dev/null +++ b/src/VirtualZmwBamRecord.cpp @@ -0,0 +1,297 @@ +// File Description +/// \file VirtualZmwBamRecord.cpp +/// \brief Implements the VirtualZmwBamRecord class. +// +// Author: Armin Töpfer + +#include "PbbamInternalConfig.h" + +#include "pbbam/virtual/VirtualZmwBamRecord.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "pbbam/virtual/VirtualRegionType.h" +#include "pbbam/virtual/VirtualRegionTypeMap.h" + +namespace PacBio { +namespace BAM { + +static_assert(std::is_copy_constructible::value, + "VirtualZmwBamRecord(const VirtualZmwBamRecord&) is not = default"); +static_assert(std::is_copy_assignable::value, + "VirtualZmwBamRecord& operator=(const VirtualZmwBamRecord&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "VirtualZmwBamRecord(VirtualZmwBamRecord&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "VirtualZmwBamRecord& operator=(VirtualZmwBamRecord&&) is not = noexcept"); + +VirtualZmwBamRecord::VirtualZmwBamRecord(std::vector unorderedSources, + const BamHeader& header) + : BamRecord{header}, sources_{std::move(unorderedSources)} +{ + // Sort sources by queryStart,queryEnd + std::sort(sources_.begin(), sources_.end(), [](const BamRecord& l1, const BamRecord& l2) { + const auto l1_qStart = l1.QueryStart(); + const auto l1_qEnd = l1.QueryEnd(); + const auto l2_qStart = l2.QueryStart(); + const auto l2_qEnd = l2.QueryEnd(); + + return std::tie(l1_qStart, l1_qEnd) < std::tie(l2_qStart, l2_qEnd); + }); + + StitchSources(); +} + +bool VirtualZmwBamRecord::HasVirtualRegionType(const VirtualRegionType regionType) const +{ + return virtualRegionsMap_.find(regionType) != virtualRegionsMap_.end(); +} + +Frames VirtualZmwBamRecord::IPDV1Frames(Orientation orientation) const +{ + const auto rawFrames = this->IPDRaw(orientation); + const std::vector rawData(rawFrames.Data().begin(), rawFrames.Data().end()); + return Frames::Decode(rawData); +} + +void VirtualZmwBamRecord::StitchSources() +{ + const auto& firstRecord = sources_[0]; + const auto& lastRecord = sources_[sources_.size() - 1]; + + std::string sequence; + std::string deletionTag; + std::string substitutionTag; + std::string alternativeLabelTag; + std::string pulseCall; + + QualityValues qualities; + QualityValues deletionQv; + QualityValues insertionQv; + QualityValues mergeQv; + QualityValues pulseMergeQv; + QualityValues substitutionQv; + QualityValues labelQv; + QualityValues alternativeLabelQv; + + Frames ipd; + Frames pw; + Frames pd; + Frames px; + std::vector pa; + std::vector pm; + std::vector sf; + std::vector pe; + + // initialize capacity + const auto stitchedSize = lastRecord.QueryEnd() - firstRecord.QueryStart(); + sequence.reserve(stitchedSize); + deletionTag.reserve(stitchedSize); + substitutionTag.reserve(stitchedSize); + alternativeLabelTag.reserve(stitchedSize); + pulseCall.reserve(stitchedSize); + qualities.reserve(stitchedSize); + deletionQv.reserve(stitchedSize); + insertionQv.reserve(stitchedSize); + mergeQv.reserve(stitchedSize); + pulseMergeQv.reserve(stitchedSize); + substitutionQv.reserve(stitchedSize); + labelQv.reserve(stitchedSize); + alternativeLabelQv.reserve(stitchedSize); + ipd.DataRaw().reserve(stitchedSize); + pw.DataRaw().reserve(stitchedSize); + pd.DataRaw().reserve(stitchedSize); + px.DataRaw().reserve(stitchedSize); + pa.reserve(stitchedSize); + pm.reserve(stitchedSize); + sf.reserve(stitchedSize); + pe.reserve(stitchedSize); + + // Stitch using tmp vars + for (auto& b : sources_) { + sequence.append(b.Sequence()); + + Utility::MoveAppend(b.Qualities(), qualities); + + if (b.HasDeletionQV()) Utility::MoveAppend(std::move(b.DeletionQV()), deletionQv); + + if (b.HasInsertionQV()) Utility::MoveAppend(std::move(b.InsertionQV()), insertionQv); + + if (b.HasMergeQV()) Utility::MoveAppend(std::move(b.MergeQV()), mergeQv); + + if (b.HasPulseMergeQV()) Utility::MoveAppend(std::move(b.PulseMergeQV()), pulseMergeQv); + + if (b.HasSubstitutionQV()) + Utility::MoveAppend(std::move(b.SubstitutionQV()), substitutionQv); + + if (b.HasLabelQV()) Utility::MoveAppend(std::move(b.LabelQV()), labelQv); + + if (b.HasAltLabelQV()) Utility::MoveAppend(std::move(b.AltLabelQV()), alternativeLabelQv); + + if (b.HasDeletionTag()) deletionTag.append(std::move(b.DeletionTag())); + + if (b.HasSubstitutionTag()) substitutionTag.append(std::move(b.SubstitutionTag())); + + if (b.HasAltLabelTag()) alternativeLabelTag.append(std::move(b.AltLabelTag())); + + if (b.HasPulseCall()) pulseCall.append(std::move(b.PulseCall())); + + if (b.HasIPD()) Utility::MoveAppend(b.IPDRaw().DataRaw(), ipd.DataRaw()); + + if (b.HasPulseWidth()) Utility::MoveAppend(b.PulseWidthRaw().DataRaw(), pw.DataRaw()); + + if (b.HasPulseCallWidth()) Utility::MoveAppend(b.PulseCallWidth().DataRaw(), px.DataRaw()); + + if (b.HasPrePulseFrames()) Utility::MoveAppend(b.PrePulseFrames().DataRaw(), pd.DataRaw()); + + if (b.HasPkmid()) Utility::MoveAppend(b.Pkmid(), pm); + + if (b.HasPkmean()) Utility::MoveAppend(b.Pkmean(), pa); + + if (b.HasPkmid2()) Utility::MoveAppend(b.Pkmid2(), pm); + + if (b.HasPkmean2()) Utility::MoveAppend(b.Pkmean2(), pa); + + if (b.HasPulseExclusion()) Utility::MoveAppend(b.PulseExclusionReason(), pe); + + if (b.HasStartFrame()) Utility::MoveAppend(b.StartFrame(), sf); + + if (b.HasScrapRegionType()) { + const VirtualRegionType regionType = b.ScrapRegionType(); + + if (!HasVirtualRegionType(regionType)) + virtualRegionsMap_[regionType] = std::vector{}; + + virtualRegionsMap_[regionType].emplace_back(regionType, b.QueryStart(), b.QueryEnd()); + } + + if (b.HasLocalContextFlags()) { + std::pair barcodes{-1, -1}; + if (b.HasBarcodes()) barcodes = b.Barcodes(); + + static constexpr const auto regionType = VirtualRegionType::SUBREAD; + if (!HasVirtualRegionType(regionType)) + virtualRegionsMap_[regionType] = std::vector{}; + + virtualRegionsMap_[regionType].emplace_back(regionType, b.QueryStart(), b.QueryEnd(), + b.LocalContextFlags(), barcodes.first, + barcodes.second); + } + + if (b.HasBarcodes() && !this->HasBarcodes()) this->Barcodes(b.Barcodes()); + + if (b.HasBarcodeQuality() && !this->HasBarcodeQuality()) + this->BarcodeQuality(b.BarcodeQuality()); + + if (b.HasReadAccuracy() && !this->HasReadAccuracy()) this->ReadAccuracy(b.ReadAccuracy()); + + if (b.HasScrapZmwType()) { + if (!this->HasScrapZmwType()) + this->ScrapZmwType(b.ScrapZmwType()); + else if (this->ScrapZmwType() != b.ScrapZmwType()) + throw std::runtime_error{"VirtualZmwBamRecord: scrap types do not match"}; + } + } + + // ReadGroup + this->ReadGroup(this->header_.ReadGroups()[0]); + + this->NumPasses(1); + + // All records should contain the same SNR and hole number + if (firstRecord.HasSignalToNoise()) this->SignalToNoise(firstRecord.SignalToNoise()); + this->HoleNumber(firstRecord.HoleNumber()); + + // QueryStart + this->QueryStart(firstRecord.QueryStart()); + this->QueryEnd(lastRecord.QueryEnd()); + this->UpdateName(); + + const std::string qualitiesStr = qualities.Fastq(); + if (sequence.size() == qualitiesStr.size()) + this->Impl().SetSequenceAndQualities(sequence, qualitiesStr); + else + this->Impl().SetSequenceAndQualities(sequence); + + // Tags as strings + if (!deletionTag.empty()) this->DeletionTag(deletionTag); + if (!substitutionTag.empty()) this->SubstitutionTag(substitutionTag); + if (!alternativeLabelTag.empty()) this->AltLabelTag(alternativeLabelTag); + if (!pulseCall.empty()) this->PulseCall(pulseCall); + + // QVs + if (!deletionQv.empty()) this->DeletionQV(deletionQv); + if (!insertionQv.empty()) this->InsertionQV(insertionQv); + if (!mergeQv.empty()) this->MergeQV(mergeQv); + if (!pulseMergeQv.empty()) this->PulseMergeQV(pulseMergeQv); + if (!substitutionQv.empty()) this->SubstitutionQV(substitutionQv); + if (!labelQv.empty()) this->LabelQV(labelQv); + if (!alternativeLabelQv.empty()) this->AltLabelQV(alternativeLabelQv); + + // PulseExclusionReason + if (!pe.empty()) this->PulseExclusionReason(pe); + + // 16 bit arrays + if (!ipd.Data().empty()) this->IPD(ipd, FrameEncodingType::LOSSLESS); + if (!pw.Data().empty()) this->PulseWidth(pw, FrameEncodingType::LOSSLESS); + if (!pa.empty()) this->Pkmean(pa); + if (!pm.empty()) this->Pkmid(pm); + if (!pd.Data().empty()) this->PrePulseFrames(pd, FrameEncodingType::LOSSLESS); + if (!px.Data().empty()) this->PulseCallWidth(px, FrameEncodingType::LOSSLESS); + + // 32 bit arrays + if (!sf.empty()) this->StartFrame(sf); + + // Determine HQREGION bases on LQREGIONS + if (HasVirtualRegionType(VirtualRegionType::LQREGION)) { + if (virtualRegionsMap_[VirtualRegionType::LQREGION].size() == 1) { + const auto lq = virtualRegionsMap_[VirtualRegionType::LQREGION][0]; + if (lq.beginPos == 0) + virtualRegionsMap_[VirtualRegionType::HQREGION].emplace_back( + VirtualRegionType::HQREGION, lq.endPos, sequence.size()); + else if (lq.endPos == static_cast(sequence.size())) + virtualRegionsMap_[VirtualRegionType::HQREGION].emplace_back( + VirtualRegionType::HQREGION, 0, lq.beginPos); + else + throw std::runtime_error{"VirtualZmwBamRecord: unknown HQREGION"}; + } else { + int beginPos = 0; + for (const auto& lqregion : virtualRegionsMap_[VirtualRegionType::LQREGION]) { + if (lqregion.beginPos - beginPos > 0) + virtualRegionsMap_[VirtualRegionType::HQREGION].emplace_back( + VirtualRegionType::HQREGION, beginPos, lqregion.beginPos); + beginPos = lqregion.endPos; + } + } + } else { + virtualRegionsMap_[VirtualRegionType::HQREGION].emplace_back(VirtualRegionType::HQREGION, 0, + sequence.size()); + } +} + +std::map> VirtualZmwBamRecord::VirtualRegionsMap() + const +{ + return virtualRegionsMap_; +} + +std::vector VirtualZmwBamRecord::VirtualRegionsTable( + const VirtualRegionType regionType) const +{ + const auto iter = virtualRegionsMap_.find(regionType); + if (iter != virtualRegionsMap_.cend()) return iter->second; + return {}; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/VirtualZmwCompositeReader.cpp b/src/VirtualZmwCompositeReader.cpp new file mode 100644 index 0000000..5bb53d2 --- /dev/null +++ b/src/VirtualZmwCompositeReader.cpp @@ -0,0 +1,73 @@ +// File Description +/// \file VirtualZmwCompositeReader.cpp +/// \brief Implements the VirtualZmwCompositeReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "VirtualZmwCompositeReader.h" + +#include + +namespace PacBio { +namespace BAM { + +VirtualZmwCompositeReader::VirtualZmwCompositeReader(const DataSet& dataset) + : currentReader_(nullptr), filter_(PbiFilter::FromDataSet(dataset)) +{ + sources_ = SourcesFromDataset(dataset); + OpenNextReader(); +} + +bool VirtualZmwCompositeReader::HasNext() { return (currentReader_ && currentReader_->HasNext()); } + +VirtualZmwBamRecord VirtualZmwCompositeReader::Next() +{ + if (currentReader_) { + const auto result = currentReader_->Next(); + if (!currentReader_->HasNext()) OpenNextReader(); + return result; + } + + // no reader active + throw std::runtime_error{ + "VirtualZmwCompositeReader: " + "no readers active, make sure you use " + "VirtualZmwCompositeReader::HasNext before " + "requesting next record"}; +} + +std::vector VirtualZmwCompositeReader::NextRaw() +{ + if (currentReader_) { + const auto result = currentReader_->NextRaw(); + if (!currentReader_->HasNext()) OpenNextReader(); + return result; + } + + // no reader active + throw std::runtime_error{ + "VirtualZmwCompositeReader: " + "no readers active, make sure you use " + "VirtualZmwCompositeReader::HasNext before " + "requesting next group of records"}; +} + +void VirtualZmwCompositeReader::OpenNextReader() +{ + currentReader_.reset(nullptr); + + // find next source pair with data + while (!sources_.empty()) { + const auto nextSource = sources_.front(); + sources_.pop_front(); + + currentReader_ = + std::make_unique(nextSource.first, nextSource.second, filter_); + if (currentReader_->HasNext()) return; + } +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/VirtualZmwCompositeReader.h b/src/VirtualZmwCompositeReader.h new file mode 100644 index 0000000..18533f6 --- /dev/null +++ b/src/VirtualZmwCompositeReader.h @@ -0,0 +1,79 @@ +// File Description +/// \file VirtualZmwCompositeReader.h +/// \brief Defines the VirtualZmwCompositeReader class. +// +// Author: Derek Barnett + +#ifndef VIRTUALZMWCOMPOSITEREADER_H +#define VIRTUALZMWCOMPOSITEREADER_H + +#include "pbbam/Config.h" + +#include +#include +#include +#include + +#include +#include + +#include "VirtualStitching.h" +#include "VirtualZmwReader.h" + +namespace PacBio { +namespace BAM { + +/// \brief The VirtualZmwCompositeReader provides an interface for +/// re-stitching "virtual" polymerase reads from their constituent parts, +/// across multiple %BAM resources from a DataSet. +/// +/// This class is essentially a DataSet-aware wrapper around +/// VirtualZmwReader, enabling multiple resources as input. See that +/// class's documentation for more info. +/// +class PBBAM_EXPORT VirtualZmwCompositeReader +{ +public: + /// \name Constructors & Related Methods + /// \{ + + explicit VirtualZmwCompositeReader(const DataSet& dataset); + + VirtualZmwCompositeReader() = delete; + VirtualZmwCompositeReader(const VirtualZmwCompositeReader&) = delete; + VirtualZmwCompositeReader(VirtualZmwCompositeReader&&) = delete; + VirtualZmwCompositeReader& operator=(const VirtualZmwCompositeReader&) = delete; + VirtualZmwCompositeReader& operator=(VirtualZmwCompositeReader&&) = delete; + ~VirtualZmwCompositeReader() = default; + + /// \} + + /// \name Stitched Record Reading + /// \{ + + /// \returns true if more ZMWs/files are available for reading. + bool HasNext(); + + /// \returns the next stitched polymerase read + VirtualZmwBamRecord Next(); + + /// \returns the next set of reads that belong to one ZMW from one %BAM + /// resource (a primary %BAM and/or its scraps file). This enables + /// stitching records in a distinct thread. + /// + std::vector NextRaw(); + + /// \} + +private: + StitchingSources sources_; + std::unique_ptr currentReader_; + PbiFilter filter_; + + void OpenNextReader(); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // VIRTUALCOMPOSITEREADER_H diff --git a/src/VirtualZmwReader.cpp b/src/VirtualZmwReader.cpp new file mode 100644 index 0000000..9dd6fa4 --- /dev/null +++ b/src/VirtualZmwReader.cpp @@ -0,0 +1,108 @@ +// File Description +/// \file VirtualZmwReader.cpp +/// \brief Implements the VirtualZmwReader class. +// +// Author: Armin Töpfer + +#include "PbbamInternalConfig.h" + +#include "VirtualZmwReader.h" + +#include + +#include "pbbam/ReadGroupInfo.h" + +namespace PacBio { +namespace BAM { + +VirtualZmwReader::VirtualZmwReader(const std::string& primaryBamFilepath, + const std::string& scrapsBamFilepath) + : VirtualZmwReader(primaryBamFilepath, scrapsBamFilepath, PbiFilter{}) +{ +} + +VirtualZmwReader::VirtualZmwReader(const std::string& primaryBamFilepath, + const std::string& scrapsBamFilepath, const PbiFilter& filter) +{ + primaryBamFile_ = std::make_unique(primaryBamFilepath); + scrapsBamFile_ = std::make_unique(scrapsBamFilepath); + + if (filter.IsEmpty()) { + primaryQuery_ = std::make_unique(*primaryBamFile_); + scrapsQuery_ = std::make_unique(*scrapsBamFile_); + } else { + primaryQuery_ = std::make_unique(filter, *primaryBamFile_); + scrapsQuery_ = std::make_unique(filter, *scrapsBamFile_); + } + + primaryIt_ = (primaryQuery_->begin()); + scrapsIt_ = (scrapsQuery_->begin()); + + stitchedHeader_ = std::make_unique(primaryBamFile_->Header().ToSam()); + + // update stitched read group in header + auto readGroups = stitchedHeader_->ReadGroups(); + if (readGroups.empty()) + throw std::runtime_error{ + "VirtualZmwReader: no read groups in header of the primary BAM file: " + + primaryBamFilepath}; + readGroups[0].ReadType("POLYMERASE"); + readGroups[0].Id(readGroups[0].MovieName(), "POLYMERASE"); + if (readGroups.size() > 1) { + std::vector singleGroup; + singleGroup.emplace_back(std::move(readGroups[0])); + readGroups = std::move(singleGroup); + stitchedHeader_->ClearReadGroups(); + } + stitchedHeader_->ReadGroups(readGroups); +} + +VirtualZmwReader::~VirtualZmwReader() = default; + +bool VirtualZmwReader::HasNext() +{ + // Return true until both iterators are at the end of the query + return primaryIt_ != primaryQuery_->end() || scrapsIt_ != scrapsQuery_->end(); +} + +// This method is not thread safe +VirtualZmwBamRecord VirtualZmwReader::Next() +{ + return VirtualZmwBamRecord{NextRaw(), *stitchedHeader_}; +} + +std::vector VirtualZmwReader::NextRaw() +{ + std::vector bamRecordVec; + + // Current hole number, the smallest of scraps and primary. + // It can be that the next ZMW is scrap only. + int currentHoleNumber; + if (primaryIt_ == primaryQuery_->end()) + currentHoleNumber = (*scrapsIt_).HoleNumber(); + else if (scrapsIt_ == scrapsQuery_->end()) + currentHoleNumber = (*primaryIt_).HoleNumber(); + else + currentHoleNumber = std::min((*primaryIt_).HoleNumber(), (*scrapsIt_).HoleNumber()); + + // collect subreads or hqregions + while (primaryIt_ != primaryQuery_->end() && currentHoleNumber == (*primaryIt_).HoleNumber()) { + bamRecordVec.push_back(*primaryIt_++); + } + + // collect scraps + while (scrapsIt_ != scrapsQuery_->end() && currentHoleNumber == (*scrapsIt_).HoleNumber()) { + bamRecordVec.push_back(*scrapsIt_++); + } + + return bamRecordVec; +} + +BamHeader VirtualZmwReader::PrimaryHeader() const { return primaryBamFile_->Header(); } + +BamHeader VirtualZmwReader::ScrapsHeader() const { return scrapsBamFile_->Header(); } + +BamHeader VirtualZmwReader::StitchedHeader() const { return *stitchedHeader_.get(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/VirtualZmwReader.h b/src/VirtualZmwReader.h new file mode 100644 index 0000000..acd6a77 --- /dev/null +++ b/src/VirtualZmwReader.h @@ -0,0 +1,90 @@ +// File Description +/// \file VirtualZmwReader.h +/// \brief Defines the VirtualZmwReader class. +// +// Author: Armin Töpfer + +#ifndef VIRTUALZMWREADER_H +#define VIRTUALZMWREADER_H + +#include "pbbam/Config.h" + +#include + +#include "pbbam/BamFile.h" +#include "pbbam/BamRecord.h" +#include "pbbam/EntireFileQuery.h" +#include "pbbam/PbiFilter.h" +#include "pbbam/PbiFilterQuery.h" +#include "pbbam/virtual/VirtualZmwBamRecord.h" + +namespace PacBio { +namespace BAM { + +class VirtualZmwReader +{ +public: + /// \brief Creates a reader that will operate on a primary %BAM file (e.g. + /// subread data) and a scraps file, consuming all reads. + /// + /// \param[in] primaryBamFilepath hqregion.bam or subreads.bam file path + /// \param[in] scrapsBamFilepath scraps.bam file path + /// + VirtualZmwReader(const std::string& primaryBamFilepath, const std::string& scrapsBamFilepath); + + /// \brief Creates a reader that will operate on a primary %BAM file (e.g. + /// subread data) and a scraps file, respecting the provided PBI + /// filter. + /// + /// \note All %BAM files must have a corresponding ".pbi" index file to use + /// the filter. You may need to call BamFile::EnsurePacBioIndexExists + /// before constructing the reader. + /// + /// \param[in] primaryBamFilepath hqregion.bam or subreads.bam file path + /// \param[in] scrapsBamFilepath scraps.bam file path + /// \param[in] filter PBI filter criteria + /// + VirtualZmwReader(const std::string& primaryBamFilepath, const std::string& scrapsBamFilepath, + const PbiFilter& filter); + + VirtualZmwReader() = delete; + VirtualZmwReader(const VirtualZmwReader&) = delete; + VirtualZmwReader(VirtualZmwReader&&) = delete; + VirtualZmwReader& operator=(const VirtualZmwReader&) = delete; + VirtualZmwReader& operator=(VirtualZmwReader&&) = delete; + ~VirtualZmwReader(); + + /// \returns the BamHeader associated with this reader's "primary" %BAM file + BamHeader PrimaryHeader() const; + + /// \returns the BamHeader associated with this reader's "scraps" %BAM file + BamHeader ScrapsHeader() const; + + /// \return the BamHeader associated with the newly stitched BAM data + BamHeader StitchedHeader() const; + + /// \returns true if more ZMWs are available for reading. + bool HasNext(); + + /// \returns the next stitched polymerase read + VirtualZmwBamRecord Next(); + + /// \returns the next set of reads that belong to one ZMW. + /// This enables stitching records in a distinct thread. + /// + std::vector NextRaw(); + +private: + std::unique_ptr primaryBamFile_; + std::unique_ptr scrapsBamFile_; + std::unique_ptr primaryQuery_; + std::unique_ptr scrapsQuery_; + internal::IQuery::iterator primaryIt_; + internal::IQuery::iterator scrapsIt_; + std::unique_ptr stitchedHeader_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // VirtualZmwREADER_H diff --git a/src/WhitelistedZmwReadStitcher.cpp b/src/WhitelistedZmwReadStitcher.cpp new file mode 100644 index 0000000..b8cf411 --- /dev/null +++ b/src/WhitelistedZmwReadStitcher.cpp @@ -0,0 +1,139 @@ +// File Description +/// \file WhitelistedZmwReadStitcher.cpp +/// \brief Implements the WhitelistedZmwReadStitcher class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/virtual/WhitelistedZmwReadStitcher.h" + +#include +#include + +#include "VirtualZmwReader.h" +#include "pbbam/PbiIndexedBamReader.h" + +namespace PacBio { +namespace BAM { + +class WhitelistedZmwReadStitcher::WhitelistedZmwReadStitcherPrivate +{ +public: + WhitelistedZmwReadStitcherPrivate(const std::vector& zmwWhitelist, + const std::string& primaryBamFilePath, + const std::string& scrapsBamFilePath) + : primaryBamFile_{std::make_unique(primaryBamFilePath)} + , scrapsBamFile_{std::make_unique(scrapsBamFilePath)} + , primaryReader_{std::make_unique(*primaryBamFile_)} + , scrapsReader_{std::make_unique(*scrapsBamFile_)} + { + // setup new header for stitched data + polyHeader_ = std::make_unique(primaryBamFile_->Header().ToSam()); + auto readGroups = polyHeader_->ReadGroups(); + if (readGroups.empty()) + throw std::runtime_error{ + "WhitelistedZmwStitcher: no read groups in header of the primary BAM file: " + + primaryBamFilePath}; + readGroups[0].ReadType("POLYMERASE"); + readGroups[0].Id(readGroups[0].MovieName(), "POLYMERASE"); + if (readGroups.size() > 1) { + std::vector singleGroup; + singleGroup.emplace_back(std::move(readGroups[0])); + readGroups = std::move(singleGroup); + polyHeader_->ClearReadGroups(); + } + polyHeader_->ReadGroups(readGroups); + + // remove ZMWs up front, that are not found in either file + PreFilterZmws(zmwWhitelist); + } + + bool HasNext() const { return !zmwWhitelist_.empty(); } + + VirtualZmwBamRecord Next() + { + auto bamRecordVec = NextRaw(); + return {std::move(bamRecordVec), *polyHeader_}; + } + + std::vector NextRaw() + { + std::vector result; + if (!HasNext()) return result; + + const auto& zmw = zmwWhitelist_.front(); + primaryReader_->Filter(PbiZmwFilter{zmw}); + scrapsReader_->Filter(PbiZmwFilter{zmw}); + + BamRecord record; + while (primaryReader_->GetNext(record)) + result.push_back(record); + while (scrapsReader_->GetNext(record)) + result.push_back(record); + + zmwWhitelist_.pop_front(); + return result; + } + + BamHeader PrimaryHeader() const { return primaryBamFile_->Header(); } + + BamHeader ScrapsHeader() const { return scrapsBamFile_->Header(); } + +private: + std::unique_ptr primaryBamFile_; + std::unique_ptr scrapsBamFile_; + std::unique_ptr primaryReader_; + std::unique_ptr scrapsReader_; + std::unique_ptr polyHeader_; + std::deque zmwWhitelist_; + + void PreFilterZmws(const std::vector& zmwWhitelist) + { + // fetch input ZMWs + const PbiRawData primaryIndex{primaryBamFile_->PacBioIndexFilename()}; + const PbiRawData scrapsIndex{scrapsBamFile_->PacBioIndexFilename()}; + const auto& primaryZmws = primaryIndex.BasicData().holeNumber_; + const auto& scrapsZmws = scrapsIndex.BasicData().holeNumber_; + + // toss them all into a set (for uniqueness & lookup here soon) + std::set inputZmws; + for (const auto& zmw : primaryZmws) + inputZmws.insert(zmw); + for (const auto& zmw : scrapsZmws) + inputZmws.insert(zmw); + + // check our requested whitelist against files' ZMWs, keep if found + const auto inputEnd = inputZmws.cend(); + for (const int32_t zmw : zmwWhitelist) { + if (inputZmws.find(zmw) != inputEnd) zmwWhitelist_.push_back(zmw); + } + } +}; + +// -------------------------------- +// ZmwReadStitcher implementation +// -------------------------------- + +WhitelistedZmwReadStitcher::WhitelistedZmwReadStitcher(const std::vector& zmwWhitelist, + const std::string& primaryBamFilePath, + const std::string& scrapsBamFilePath) + : d_{std::make_unique(zmwWhitelist, primaryBamFilePath, + scrapsBamFilePath)} +{ +} + +WhitelistedZmwReadStitcher::~WhitelistedZmwReadStitcher() = default; + +bool WhitelistedZmwReadStitcher::HasNext() const { return d_->HasNext(); } + +VirtualZmwBamRecord WhitelistedZmwReadStitcher::Next() { return d_->Next(); } + +std::vector WhitelistedZmwReadStitcher::NextRaw() { return d_->NextRaw(); } + +BamHeader WhitelistedZmwReadStitcher::PrimaryHeader() const { return d_->PrimaryHeader(); } + +BamHeader WhitelistedZmwReadStitcher::ScrapsHeader() const { return d_->ScrapsHeader(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/XmlReader.cpp b/src/XmlReader.cpp new file mode 100644 index 0000000..b2b1317 --- /dev/null +++ b/src/XmlReader.cpp @@ -0,0 +1,236 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "XmlReader.h" + +#include +#include +#include +#include +#include +#include + +#include "pbbam/StringUtilities.h" +#include "pugixml/pugixml.hpp" + +using DataSetElement = PacBio::BAM::internal::DataSetElement; +using FromInputXml = PacBio::BAM::internal::FromInputXml; + +namespace PacBio { +namespace BAM { +namespace { + +std::unique_ptr MakeDataSetBase(const pugi::xml_node& xmlNode) +{ + const FromInputXml fromInputXml{}; + std::string name = xmlNode.name(); + const auto foundColon = name.find(':'); + if (foundColon != std::string::npos) { + name = name.substr(foundColon + 1); + } + + const auto type = ElementTypeFromName(name); + switch (type) { + case XmlElementType::ALIGNMENT_SET: + return std::make_unique(fromInputXml); + case XmlElementType::BARCODE_SET: + return std::make_unique(fromInputXml); + case XmlElementType::CONSENSUS_ALIGNMENT_SET: + return std::make_unique(fromInputXml); + case XmlElementType::CONSENSUS_READ_SET: + return std::make_unique(fromInputXml); + case XmlElementType::CONTIG_SET: + return std::make_unique(fromInputXml); + case XmlElementType::HDF_SUBREAD_SET: + return std::make_unique(fromInputXml); + case XmlElementType::REFERENCE_SET: + return std::make_unique(fromInputXml); + case XmlElementType::SUBREAD_SET: + return std::make_unique(fromInputXml); + case XmlElementType::TRANSCRIPT_SET: + return std::make_unique(fromInputXml); + case XmlElementType::TRANSCRIPT_ALIGNMENT_SET: + return std::make_unique(fromInputXml); + case XmlElementType::GENERIC_DATASET: + return std::make_unique(fromInputXml); + default: + // unreachable + throw std::runtime_error{"XmlReader: unknown data set label: " + name}; + } +} + +std::shared_ptr MakeElement(const pugi::xml_node& xmlNode) +{ + std::string name = xmlNode.name(); + const auto foundColon = name.find(':'); + if (foundColon != std::string::npos) { + name = name.substr(foundColon + 1); + } + + const FromInputXml fromInputXml{}; + const auto type = ElementTypeFromName(name); + switch (type) { + case XmlElementType::DATASET_METADATA: + return std::make_shared(fromInputXml); + case XmlElementType::BIOSAMPLE: + return std::make_shared("", fromInputXml); + case XmlElementType::BIOSAMPLES: + return std::make_shared(fromInputXml); + case XmlElementType::DNA_BARCODE: + return std::make_shared("", fromInputXml); + case XmlElementType::DNA_BARCODES: + return std::make_shared(fromInputXml); + case XmlElementType::EXTENSION: + return std::make_shared(fromInputXml); + case XmlElementType::EXTENSIONS: + return std::make_shared(fromInputXml); + case XmlElementType::EXTERNAL_RESOURCE: + return std::make_shared("", "", fromInputXml); + case XmlElementType::EXTERNAL_RESOURCES: + return std::make_shared(fromInputXml); + case XmlElementType::FILE_INDEX: + return std::make_shared("", "", fromInputXml); + case XmlElementType::FILE_INDICES: + return std::make_shared(fromInputXml); + case XmlElementType::FILTER: + return std::make_shared(fromInputXml); + case XmlElementType::FILTERS: + return std::make_shared(fromInputXml); + case XmlElementType::PARENT_TOOL: + return std::make_shared(fromInputXml); + case XmlElementType::PROPERTY: + return std::make_shared("", "", "", fromInputXml); + case XmlElementType::PROPERTIES: + return std::make_shared(fromInputXml); + case XmlElementType::PROVENANCE: + return std::make_shared(fromInputXml); + case XmlElementType::ALIGNMENT_SET: + return std::make_shared(fromInputXml); + case XmlElementType::BARCODE_SET: + return std::make_shared(fromInputXml); + case XmlElementType::CONSENSUS_ALIGNMENT_SET: + return std::make_shared(fromInputXml); + case XmlElementType::CONSENSUS_READ_SET: + return std::make_shared(fromInputXml); + case XmlElementType::CONTIG_SET: + return std::make_shared(fromInputXml); + case XmlElementType::HDF_SUBREAD_SET: + return std::make_shared(fromInputXml); + case XmlElementType::SUBREAD_SET: + return std::make_shared(fromInputXml); + case XmlElementType::REFERENCE_SET: + return std::make_shared(fromInputXml); + case XmlElementType::TRANSCRIPT_SET: + return std::make_shared(fromInputXml); + case XmlElementType::TRANSCRIPT_ALIGNMENT_SET: + return std::make_shared(fromInputXml); + case XmlElementType::SUBDATASETS: + return std::make_shared(fromInputXml); + case XmlElementType::GENERIC_DATASET: + return std::make_shared(fromInputXml); + case XmlElementType::GENERIC_ELEMENT: + return std::make_shared(name, fromInputXml); + default: + // unreachable + throw std::runtime_error{"XmlReader: unknown data element label: " + name}; + } +} + +void UpdateRegistry(const std::string& attributeName, const std::string& attributeValue, + NamespaceRegistry& registry) +{ + std::vector nameParts = Split(attributeName, ':'); + assert(!nameParts.empty()); + if (nameParts.size() > 2) + throw std::runtime_error{"XmlReader: malformed xmlns attribute: " + attributeName}; + + const bool isDefault = (nameParts.size() == 1); + const XsdType xsd = registry.XsdForUri(attributeValue); + + if (isDefault) + registry.SetDefaultXsd(xsd); + else { + assert(nameParts.size() == 2); + const std::string& name = nameParts.at(1); + const std::string& uri = attributeValue; + NamespaceInfo namespaceInfo(name, uri); + registry.Register(xsd, namespaceInfo); + } +} + +void FromXml(const pugi::xml_node& xmlNode, DataSetElement& parent) +{ + // ignore non-named XML nodes + // + // pugi::xml separates XML parts into more node types than we use + // + const std::string label = xmlNode.name(); + if (label.empty()) return; + + auto e = MakeElement(xmlNode); + e->Label(xmlNode.name()); + e->Text(xmlNode.text().get()); + + // iterate attributes + auto attrIter = xmlNode.attributes_begin(); + auto attrEnd = xmlNode.attributes_end(); + for (; attrIter != attrEnd; ++attrIter) + e->Attribute(attrIter->name(), attrIter->value()); + + // iterate children, recursively building up subtree + auto childIter = xmlNode.begin(); + auto childEnd = xmlNode.end(); + for (; childIter != childEnd; ++childIter) { + pugi::xml_node childNode = *childIter; + FromXml(childNode, *e.get()); + } + + parent.AddChild(e); +} + +} // namespace + +std::unique_ptr XmlReader::FromStream(std::istream& in) +{ + pugi::xml_document doc; + const pugi::xml_parse_result loadResult = doc.load(in); + if (loadResult.status != pugi::status_ok) + throw std::runtime_error{"XmlReader: could not read XML file, error code:" + + std::to_string(loadResult.status)}; + + // parse top-level attributes + pugi::xml_node rootNode = doc.document_element(); + if (rootNode == pugi::xml_node()) + throw std::runtime_error{"XmlReader: could not fetch XML root node"}; + + // create dataset matching type strings + auto dataset = MakeDataSetBase(rootNode); + dataset->Label(rootNode.name()); + + // iterate attributes, capture namespace info + const std::string xmlnsPrefix("xmlns"); + auto attrIter = rootNode.attributes_begin(); + auto attrEnd = rootNode.attributes_end(); + for (; attrIter != attrEnd; ++attrIter) { + const std::string name = attrIter->name(); + const std::string value = attrIter->value(); + dataset->Attribute(name, value); + if (name.find(xmlnsPrefix) == 0) { + UpdateRegistry(name, value, dataset->Namespaces()); + } + } + + // iterate children, recursively building up subtree + auto childIter = rootNode.begin(); + auto childEnd = rootNode.end(); + for (; childIter != childEnd; ++childIter) { + pugi::xml_node childNode = *childIter; + FromXml(childNode, *dataset.get()); + } + + return dataset; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/XmlReader.h b/src/XmlReader.h new file mode 100644 index 0000000..352dc40 --- /dev/null +++ b/src/XmlReader.h @@ -0,0 +1,25 @@ +// Author: Derek Barnett + +#ifndef XMLREADER_H +#define XMLREADER_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/DataSet.h" + +namespace PacBio { +namespace BAM { + +class XmlReader +{ +public: + static std::unique_ptr FromStream(std::istream& in); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // XMLREADER_H diff --git a/src/XmlWriter.cpp b/src/XmlWriter.cpp new file mode 100644 index 0000000..24fbd69 --- /dev/null +++ b/src/XmlWriter.cpp @@ -0,0 +1,167 @@ +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "XmlWriter.h" + +#include +#include +#include +#include + +#include "pbbam/DataSet.h" + +#include "FileUtils.h" +#include "pugixml/pugixml.hpp" + +using DataSetElement = PacBio::BAM::internal::DataSetElement; + +namespace PacBio { +namespace BAM { +namespace { + +std::string Prefix(const std::string& input) +{ + const auto colonFound = input.find(':'); + if (colonFound == std::string::npos || colonFound == 0) return std::string(); + return input.substr(0, colonFound); +} + +std::string OutputName(const DataSetElement& node, const NamespaceRegistry& registry) +{ + // if from input XML, respect the namespaces given + if (node.IsVerbatimLabel()) return node.QualifiedNameLabel(); + + // otherwise, probably user-generated + else { + // if no namespace prefix, prepend the appropriate one & return + if (node.PrefixLabel().empty()) { + static const std::string colon = ":"; + auto xsdType = node.Xsd(); + if (xsdType == XsdType::NONE) + xsdType = registry.XsdForElement(node.LocalNameLabel().to_string()); + return registry.Namespace(xsdType).Name() + colon + node.LocalNameLabel().to_string(); + } + // otherwise, has prefix - return full name + else + return node.QualifiedNameLabel(); + } +} + +void ToXml(const DataSetElement& node, const NamespaceRegistry& registry, + std::map& xsdPrefixesUsed, pugi::xml_node& parentXml, + const DataSetBase& dataset) +{ + // create child of parent, w/ label & text + const auto label = OutputName(node, registry); + if (label.empty()) return; // error? + auto xmlNode = parentXml.append_child(label.c_str()); + + if (!node.Text().empty()) xmlNode.text().set(node.Text().c_str()); + + // store XSD type for later + const auto prefix = Prefix(label); + if (!prefix.empty()) xsdPrefixesUsed[node.Xsd()] = prefix; + + // add attributes + for (const auto& attribute : node.Attributes()) { + const auto& name = attribute.first; + if (name.empty()) continue; + + auto attr = xmlNode.append_attribute(name.c_str()); + std::string value = attribute.second.c_str(); + // "absolutize" any paths, except relative paths from verbatim input XML + if (!dataset.FromInputXml() && name == "ResourceId") + value = FileUtils::ResolvedFilePath(value, dataset.Path()); + attr.set_value(value.c_str()); + } + + // additional stuff later? (e.g. comments) + + // iterate children, recursively building up subtree + for (const auto& child : node.Children()) + ToXml(*child, registry, xsdPrefixesUsed, xmlNode, dataset); +} + +} // namespace + +void XmlWriter::ToStream(const DataSetBase& dataset, std::ostream& out) +{ + pugi::xml_document doc; + + const auto& registry = dataset.Namespaces(); + + // create top-level dataset XML node + const auto label = OutputName(dataset, registry); + if (label.empty()) throw std::runtime_error{"XmlReader: could not convert dataset node to XML"}; + auto root = doc.append_child(label.c_str()); + + const auto& text = dataset.Text(); + if (!text.empty()) root.text().set(text.c_str()); + + // add top-level attributes + for (const auto& attribute : dataset.Attributes()) { + const auto& name = attribute.first; + const auto& value = attribute.second; + if (name.empty()) continue; + auto attr = root.append_attribute(name.c_str()); + attr.set_value(value.c_str()); + } + + std::map xsdPrefixesUsed; + xsdPrefixesUsed[dataset.Xsd()] = Prefix(label); + + // iterate children, recursively building up subtree + for (const auto& child : dataset.Children()) + ToXml(*child, registry, xsdPrefixesUsed, root, dataset); + + // write XML to stream + auto decl = doc.prepend_child(pugi::node_declaration); + decl.append_attribute("version") = "1.0"; + decl.append_attribute("encoding") = "utf-8"; + + // add XSD namespace attributes + auto xmlnsDefaultAttribute = root.attribute("xmlns"); + if (xmlnsDefaultAttribute.empty()) { + xmlnsDefaultAttribute = root.append_attribute("xmlns"); + xmlnsDefaultAttribute.set_value(registry.DefaultNamespace().Uri().c_str()); + } + auto xsiAttribute = root.attribute("xmlns:xsi"); + if (xsiAttribute.empty()) { + xsiAttribute = root.append_attribute("xmlns:xsi"); + xsiAttribute.set_value("http://www.w3.org/2001/XMLSchema-instance"); + } + auto xsiSchemaLocationAttribute = root.attribute("xsi:schemaLocation"); + if (xsiSchemaLocationAttribute.empty()) { + xsiSchemaLocationAttribute = root.append_attribute("xsi:schemaLocation"); + xsiSchemaLocationAttribute.set_value(registry.DefaultNamespace().Uri().c_str()); + } + + static const std::string xmlnsPrefix = "xmlns:"; + for (const auto prefixIter : xsdPrefixesUsed) { + const auto& xsdType = prefixIter.first; + const auto& prefix = prefixIter.second; + if (xsdType == XsdType::NONE || prefix.empty()) continue; + + const auto& nsInfo = registry.Namespace(xsdType); + assert(nsInfo.Name() == prefix); + const auto xmlnsName = xmlnsPrefix + prefix; + auto xmlnsAttribute = root.attribute(xmlnsName.c_str()); + if (xmlnsAttribute.empty()) { + xmlnsAttribute = root.append_attribute(xmlnsName.c_str()); + xmlnsAttribute.set_value(nsInfo.Uri().c_str()); + } + } + + // "no escapes" to allow explicit ">" "<" comparison operators in filter parameters + // we may remove this if/when comparison is separated from the value + doc.save(out, "\t", pugi::format_default | pugi::format_no_escapes, pugi::encoding_utf8); +} + +void XmlWriter::ToStream(const std::unique_ptr& dataset, std::ostream& out) +{ + ToStream(*dataset.get(), out); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/XmlWriter.h b/src/XmlWriter.h new file mode 100644 index 0000000..5a3f481 --- /dev/null +++ b/src/XmlWriter.h @@ -0,0 +1,26 @@ +// Author: Derek Barnett + +#ifndef XMLWRITER_H +#define XMLWRITER_H + +#include "pbbam/Config.h" + +#include +#include + +namespace PacBio { +namespace BAM { + +class DataSetBase; + +class XmlWriter +{ +public: + static void ToStream(const DataSetBase& dataset, std::ostream& out); + static void ToStream(const std::unique_ptr& dataset, std::ostream& out); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // XMLWRITER_H diff --git a/src/ZmwChunkedFastaReader.cpp b/src/ZmwChunkedFastaReader.cpp new file mode 100644 index 0000000..be061d1 --- /dev/null +++ b/src/ZmwChunkedFastaReader.cpp @@ -0,0 +1,146 @@ +// File Description +/// \file ZmwChunkedFastaReader.cpp +/// \brief Implements the ZmwChunkedFastaReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ZmwChunkedFastaReader.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "pbbam/FaiIndex.h" +#include "pbbam/FormatUtils.h" + +#include "MemoryUtils.h" +#include "ZmwChunkedFastxBgzfReader.h" +#include "ZmwChunkedFastxReaderImpl.h" +#include "ZmwChunkedFastxTextReader.h" + +namespace PacBio { +namespace BAM { +namespace { + +std::unique_ptr MakeFastaReaderImpl(std::string filename, + const size_t numChunks) +{ + // validate extension + if (!FormatUtils::IsFastaFilename(filename)) { + throw std::runtime_error{"ZmwChunkedFastaReader: filename '" + filename + + "' is not recognized as a FASTA file."}; + } + + // determine subsequence "loader" from compression type: plain-text, bgzf, or unsupported + const auto compressionType = FormatUtils::CompressionType(filename); + switch (compressionType) { + + case HtslibCompression::NONE: + return std::make_unique(std::move(filename), numChunks); + case HtslibCompression::BGZIP: + return std::make_unique(std::move(filename), numChunks); + + case HtslibCompression::GZIP: { + std::ostringstream msg; + msg << "ZmwChunkedFastaReader: random-access is not supported for plain gzipped " + "file " + << filename << "\n\n" + << "Compressed files must be bgzipped, with accompanying *.gzi " + "index.\n\n" + << "To keep the original gzipped file unchanged:\n" + << " $ gunzip -c " << filename << " > \n" + << "or discard the gzipped file:\n" + << " $ gunzip " << filename << '\n' + << '\n' + << "Re-compress & create *.gzi index:\n" + << " $ bgzip --index \n\n"; + throw std::runtime_error{msg.str()}; + } + default: + assert(false); // should never get here, the way htslib currently determines type + throw std::runtime_error{ + "ZmwChunkedFastaReader: could not determine compression type for file: " + + filename}; + } +} + +} // namespace + +class ZmwChunkedFastaReader::ZmwChunkedFastaReaderPrivate +{ +public: + explicit ZmwChunkedFastaReaderPrivate(const std::string& fn, const size_t numChunks) + : reader_{MakeFastaReaderImpl(std::move(fn), numChunks)} + { + assert(reader_->chunker_.NumChunks() != 0); + Chunk(0); + } + + void Chunk(size_t chunkId) + { + const auto& chunk = reader_->chunker_.Chunk(chunkId); + remaining = chunk.NumRecords; + reader_->Seek(chunk.FirstSeqOffset); + currentChunkId_ = chunkId; + firstRecord = true; + } + + bool GetNext(FastaSequence& record) + { + if (remaining == 0) return false; + record = reader_->ReadNextFasta(firstRecord); + if (firstRecord) { + record.Name(reader_->chunker_.Chunk(currentChunkId_).FirstSeqName); + firstRecord = false; + } + --remaining; + return true; + } + + // reader + std::unique_ptr reader_; + size_t currentChunkId_ = 0; + bool firstRecord; + size_t remaining; +}; + +static_assert(!std::is_copy_constructible::value, + "ZmwChunkedFastaReader(const ZmwChunkedFastaReader&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "ZmwChunkedFastaReader& operator=(const ZmwChunkedFastaReader&) is not = delete"); + +ZmwChunkedFastaReader::ZmwChunkedFastaReader(const std::string& fn, const size_t numChunks) + : internal::QueryBase{} + , d_{std::make_unique(fn, numChunks)} +{ +} + +ZmwChunkedFastaReader::ZmwChunkedFastaReader(ZmwChunkedFastaReader&&) noexcept = default; + +ZmwChunkedFastaReader& ZmwChunkedFastaReader::operator=(ZmwChunkedFastaReader&&) noexcept = default; + +ZmwChunkedFastaReader::~ZmwChunkedFastaReader() = default; + +size_t ZmwChunkedFastaReader::NumChunks() const { return d_->reader_->chunker_.NumChunks(); } + +ZmwChunkedFastaReader& ZmwChunkedFastaReader::Chunk(size_t chunkId) +{ + d_->Chunk(chunkId); + return *this; +} + +size_t ZmwChunkedFastaReader::Chunk() const { return d_->currentChunkId_; } + +bool ZmwChunkedFastaReader::GetNext(FastaSequence& record) { return d_->GetNext(record); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ZmwChunkedFastqReader.cpp b/src/ZmwChunkedFastqReader.cpp new file mode 100644 index 0000000..3bbcf2b --- /dev/null +++ b/src/ZmwChunkedFastqReader.cpp @@ -0,0 +1,146 @@ +// File Description +/// \file ZmwChunkedFastqReader.cpp +/// \brief Implements the ZmwChunkedFastqReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ZmwChunkedFastqReader.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "pbbam/FaiIndex.h" +#include "pbbam/FormatUtils.h" + +#include "MemoryUtils.h" +#include "ZmwChunkedFastxBgzfReader.h" +#include "ZmwChunkedFastxReaderImpl.h" +#include "ZmwChunkedFastxTextReader.h" + +namespace PacBio { +namespace BAM { +namespace { + +std::unique_ptr MakeFastqReaderImpl(std::string filename, + const size_t numChunks) +{ + // validate extension + if (!FormatUtils::IsFastqFilename(filename)) { + throw std::runtime_error{"ZmwChunkedFastqReader: filename '" + filename + + "' is not recognized as a FASTA file."}; + } + + // determine subsequence "loader" from compression type: plain-text, bgzf, or unsupported + const auto compressionType = FormatUtils::CompressionType(filename); + switch (compressionType) { + + case HtslibCompression::NONE: + return std::make_unique(std::move(filename), numChunks); + case HtslibCompression::BGZIP: + return std::make_unique(std::move(filename), numChunks); + + case HtslibCompression::GZIP: { + std::ostringstream msg; + msg << "ZmwChunkedFastqReader: random-access is not supported for plain gzipped " + "file " + << filename << "\n\n" + << "Compressed files must be bgzipped, with accompanying *.gzi " + "index.\n\n" + << "To keep the original gzipped file unchanged:\n" + << " $ gunzip -c " << filename << " > \n" + << "or discard the gzipped file:\n" + << " $ gunzip " << filename << '\n' + << '\n' + << "Re-compress & create *.gzi index:\n" + << " $ bgzip --index \n\n"; + throw std::runtime_error{msg.str()}; + } + default: + assert(false); // should never get here, the way htslib currently determines type + throw std::runtime_error{ + "ZmwChunkedFastqReader: could not determine compression type for file: " + + filename}; + } +} + +} // namespace + +class ZmwChunkedFastqReader::ZmwChunkedFastqReaderPrivate +{ +public: + explicit ZmwChunkedFastqReaderPrivate(const std::string& fn, const size_t numChunks) + : reader_{MakeFastqReaderImpl(std::move(fn), numChunks)} + { + assert(reader_->chunker_.NumChunks() != 0); + Chunk(0); + } + + void Chunk(size_t chunkId) + { + const auto& chunk = reader_->chunker_.Chunk(chunkId); + remaining = chunk.NumRecords; + reader_->Seek(chunk.FirstSeqOffset); + currentChunkId_ = chunkId; + firstRecord = true; + } + + bool GetNext(FastqSequence& record) + { + if (remaining == 0) return false; + record = reader_->ReadNextFastq(firstRecord); + if (firstRecord) { + record.Name(reader_->chunker_.Chunk(currentChunkId_).FirstSeqName); + firstRecord = false; + } + --remaining; + return true; + } + + // reader + std::unique_ptr reader_; + size_t currentChunkId_ = 0; + bool firstRecord; + size_t remaining; +}; + +static_assert(!std::is_copy_constructible::value, + "ZmwChunkedFastqReader(const ZmwChunkedFastqReader&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "ZmwChunkedFastqReader& operator=(const ZmwChunkedFastqReader&) is not = delete"); + +ZmwChunkedFastqReader::ZmwChunkedFastqReader(const std::string& fn, const size_t numChunks) + : internal::QueryBase{} + , d_{std::make_unique(fn, numChunks)} +{ +} + +ZmwChunkedFastqReader::ZmwChunkedFastqReader(ZmwChunkedFastqReader&&) noexcept = default; + +ZmwChunkedFastqReader& ZmwChunkedFastqReader::operator=(ZmwChunkedFastqReader&&) noexcept = default; + +ZmwChunkedFastqReader::~ZmwChunkedFastqReader() = default; + +size_t ZmwChunkedFastqReader::NumChunks() const { return d_->reader_->chunker_.NumChunks(); } + +ZmwChunkedFastqReader& ZmwChunkedFastqReader::Chunk(size_t chunkId) +{ + d_->Chunk(chunkId); + return *this; +} + +size_t ZmwChunkedFastqReader::Chunk() const { return d_->currentChunkId_; } + +bool ZmwChunkedFastqReader::GetNext(FastqSequence& record) { return d_->GetNext(record); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ZmwChunkedFastxBgzfReader.cpp b/src/ZmwChunkedFastxBgzfReader.cpp new file mode 100644 index 0000000..7f81f18 --- /dev/null +++ b/src/ZmwChunkedFastxBgzfReader.cpp @@ -0,0 +1,157 @@ +// File Description +/// \file BgzFastqLoader.cpp +/// \brief Implements the ZmwChunkedFastxBgzfReaderr class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "ZmwChunkedFastxBgzfReader.h" + +#include +#include +#include + +namespace PacBio { +namespace BAM { + +ZmwChunkedFastxBgzfReader::ZmwChunkedFastxBgzfReader(std::string filename, const size_t numChunks) + : ZmwChunkedFastxReaderImpl{std::move(filename), numChunks} + , file_{bgzf_open(fastxFilename_.c_str(), "r")} + , seq_{kseq_init(file_.get())} +{ + // check BGZF file handle + if (file_ == nullptr) { + std::ostringstream msg; + msg << "ZmwChunkedFastxBgzfReader: could not open file for reading\n" + << " file: " << fastxFilename_ << '\n'; + throw std::runtime_error{msg.str()}; + } + + // check kseq sequence handle + assert(seq_ != nullptr); + + // load BGZF index data (*.gzi) + const auto result = bgzf_index_load(file_.get(), fastxFilename_.c_str(), ".gzi"); + if (result != 0) { + std::ostringstream msg; + msg << "ZmwChunkedFastxBgzfReader: could not load bgzf index data\n" + << " file: " << fastxFilename_ << '\n' + << " index file: " << fastxFilename_ << ".gzi\n"; + throw std::runtime_error{msg.str()}; + } +} + +int ZmwChunkedFastxBgzfReader::FetchRecord(bool skipName) +{ + // NOTE: kseq_read assumes it is at the beginning of "next" sequence's name. + // However, here the file handle may already point to the first base after + // seeking using FAI. So we optionally load the name. + + int c; + kseq_t* seq = seq_.get(); + kstream_t* ks = seq->f; + seq_->comment.l = seq_->seq.l = seq_->qual.l = 0; /* reset all members */ + + if (!skipName) { + + if (seq->last_char == 0) { /* then jump to the next header line */ + while ((c = ks_getc(ks)) != -1 && c != '>' && c != '@') + ; + if (c == -1) return -1; /* end of file */ + seq->last_char = c; + } /* else: the first header char has been read in the previous call */ + + if (ks_getuntil(ks, 0, &seq->name, &c) < 0) return -1; /* normal exit: EOF */ + if (c != '\n') ks_getuntil(ks, KS_SEP_LINE, &seq->comment, 0); /* read FASTA/Q comment */ + } + + if (seq_->seq.s == 0) { /* we can do this in the loop below, but that is slower */ + seq_->seq.m = 256; + seq_->seq.s = (char*)malloc(seq_->seq.m); + } + while ((c = ks_getc(ks)) != -1 && c != '>' && c != '+' && c != '@') { + if (c == '\n') continue; /* skip empty lines */ + seq_->seq.s[seq_->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ + ks_getuntil2(ks, KS_SEP_LINE, &seq_->seq, 0, 1); /* read the rest of the line */ + } + + if (c == '>' || c == '@') seq_->last_char = c; /* the first header char has been read */ + if (seq_->seq.l + 1 >= + seq_->seq.m) { /* seq_->seq.s[seq_->seq.l] below may be out of boundary */ + seq_->seq.m = seq_->seq.l + 2; + kroundup32(seq_->seq.m); /* rounded to the next closest 2^k */ + seq_->seq.s = (char*)realloc(seq_->seq.s, seq_->seq.m); + } + seq_->seq.s[seq_->seq.l] = 0; /* null terminated string */ + + if (c != '+') return seq_->seq.l; /* FASTA */ + if (seq_->qual.m < seq_->seq.m) { /* allocate memory for qual in case insufficient */ + seq_->qual.m = seq_->seq.m; + seq_->qual.s = (char*)realloc(seq_->qual.s, seq_->qual.m); + } + + while ((c = ks_getc(ks)) != -1 && c != '\n') + ; /* skip the rest of '+' line */ + if (c == -1) return -2; /* error: no quality string */ + while (ks_getuntil2(ks, KS_SEP_LINE, &seq_->qual, 0, 1) >= 0 && seq_->qual.l < seq_->seq.l) + ; + + seq_->last_char = 0; /* we have not come to the next header line */ + + if (seq_->seq.l != seq_->qual.l) return -2; /* error: qual string is of a different length */ + return seq_->seq.l; +} + +FastaSequence ZmwChunkedFastxBgzfReader::ReadNextFasta(bool skipName) +{ + // read sequence + const auto result = FetchRecord(skipName); + if (result < 0) { + std::ostringstream msg; + msg << "ZmwChunkedFastxBgzfReader: error reading from\n" + << " file: " << fastxFilename_ << '\n' + << " reason: likely truncated quality string\n"; + throw std::runtime_error{msg.str()}; + } + + // return FASTQ + std::string name = (skipName ? "" : std::string{seq_->name.s, seq_->name.l}); + std::string bases{seq_->seq.s, seq_->seq.l}; + return FastaSequence{std::move(name), std::move(bases)}; +} + +FastqSequence ZmwChunkedFastxBgzfReader::ReadNextFastq(bool skipName) +{ + // read sequence + const auto result = FetchRecord(skipName); + if (result < 0) { + std::ostringstream msg; + msg << "ZmwChunkedFastxBgzfReader: error reading from\n" + << " file: " << fastxFilename_ << '\n' + << " reason: likely truncated quality string\n"; + throw std::runtime_error{msg.str()}; + } + + // return FASTQ + std::string name = (skipName ? "" : std::string{seq_->name.s, seq_->name.l}); + std::string bases{seq_->seq.s, seq_->seq.l}; + QualityValues quals{std::string{seq_->qual.s, seq_->qual.l}}; + return FastqSequence{std::move(name), std::move(bases), std::move(quals)}; +} + +void ZmwChunkedFastxBgzfReader::Seek(uint64_t pos) +{ + // seek to sequence 'id' & reset kseq handle + auto result = bgzf_useek(file_.get(), pos, SEEK_SET); + if (result != 0) { + std::ostringstream msg; + msg << "ZmwChunkedFastxBgzfReader: could not seek to requested pos: " << pos << '\n' + << " in file: " << fastxFilename_; + throw std::runtime_error{msg.str()}; + } + ks_rewind(seq_->f); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/ZmwChunkedFastxBgzfReader.h b/src/ZmwChunkedFastxBgzfReader.h new file mode 100644 index 0000000..5426bd9 --- /dev/null +++ b/src/ZmwChunkedFastxBgzfReader.h @@ -0,0 +1,53 @@ +// File Description +/// \file ZmwChunkedFastxBgzfReader.h +/// \brief Defines the ZmwChunkedFastxBgzfReader class. +// +// Author: Derek Barnett + +#ifndef ZMWCHUNKEDFASTXBGZFREADER_H +#define ZMWCHUNKEDFASTXBGZFREADER_H + +#include "pbbam/Config.h" + +#include "ZmwChunkedFastxReaderImpl.h" + +#include + +#include + +#include "MemoryUtils.h" + +namespace PacBio { +namespace BAM { + +class ZmwChunkedFastxBgzfReader final : public ZmwChunkedFastxReaderImpl +{ +public: + ZmwChunkedFastxBgzfReader(std::string filename, const size_t numChunks); + + void Seek(uint64_t pos) final; + FastaSequence ReadNextFasta(bool skipName) final; + FastqSequence ReadNextFastq(bool skipName) final; + +private: + int FetchRecord(bool getName); + + // specialize kseq_t for BGZF handle + KSEQ_INIT(BGZF*, bgzf_read); + struct KSeqDeleter + { + void operator()(kseq_t* seq) const + { + if (seq) kseq_destroy(seq); + seq = nullptr; + } + }; + + std::unique_ptr file_; + std::unique_ptr seq_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWCHUNKEDFASTXBGZFREADER_H \ No newline at end of file diff --git a/src/ZmwChunkedFastxReaderImpl.cpp b/src/ZmwChunkedFastxReaderImpl.cpp new file mode 100644 index 0000000..fa57596 --- /dev/null +++ b/src/ZmwChunkedFastxReaderImpl.cpp @@ -0,0 +1,25 @@ +// File Description +/// \file ZmwChunkedFastxReaderImpl.cpp +/// \brief Implements the ZmwChunkedFastxReaderImpl class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "ZmwChunkedFastxReaderImpl.h" + +namespace PacBio { +namespace BAM { + +ZmwChunkedFastxReaderImpl::ZmwChunkedFastxReaderImpl(std::string filename, const size_t numChunks) + : fastxFilename_{std::move(filename)} + , faiFilename_{fastxFilename_ + ".fai"} + , index_{faiFilename_} + , chunker_{index_, numChunks} +{ +} + +ZmwChunkedFastxReaderImpl::~ZmwChunkedFastxReaderImpl() = default; + +} // namespace BAM +} // namespace PacBio diff --git a/src/ZmwChunkedFastxReaderImpl.h b/src/ZmwChunkedFastxReaderImpl.h new file mode 100644 index 0000000..c722b01 --- /dev/null +++ b/src/ZmwChunkedFastxReaderImpl.h @@ -0,0 +1,45 @@ +// File Description +/// \file ZmwChunkedFastxReaderImpl.h +/// \brief Defines the ZmwChunkedFastxReaderImpl class. +// +// Author: Derek Barnett + +#ifndef ZMWCHUNKEDFASTXREADERIMPL_H +#define ZMWCHUNKEDFASTXREADERIMPL_H + +#include "pbbam/Config.h" + +#include +#include + +#include "pbbam/FaiIndex.h" +#include "pbbam/FastaSequence.h" +#include "pbbam/FastqSequence.h" + +#include "FaiZmwChunker.h" + +namespace PacBio { +namespace BAM { + +class ZmwChunkedFastxReaderImpl +{ +public: + virtual ~ZmwChunkedFastxReaderImpl(); + + virtual void Seek(uint64_t pos) = 0; + virtual FastaSequence ReadNextFasta(bool skipName) = 0; + virtual FastqSequence ReadNextFastq(bool skipName) = 0; + + std::string fastxFilename_; + std::string faiFilename_; + FaiIndex index_; + FaiZmwChunker chunker_; + +protected: + ZmwChunkedFastxReaderImpl(std::string fastxFilename, const size_t numChunks); +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWCHUNKEDFASTXREADERIMPL_H \ No newline at end of file diff --git a/src/ZmwChunkedFastxTextReader.cpp b/src/ZmwChunkedFastxTextReader.cpp new file mode 100644 index 0000000..6b219f3 --- /dev/null +++ b/src/ZmwChunkedFastxTextReader.cpp @@ -0,0 +1,157 @@ +// File Description +/// \file ZmwChunkedFastxTextReader.cpp +/// \brief Implements the ZmwChunkedFastxTextReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "ZmwChunkedFastxTextReader.h" + +#include +#include +#include + +#include +#include +#include +#include + +namespace PacBio { +namespace BAM { + +ZmwChunkedFastxTextReader::ZmwChunkedFastxTextReader(std::string filename, const size_t numChunks) + : ZmwChunkedFastxReaderImpl{std::move(filename), numChunks} + , file_{fopen(fastxFilename_.c_str(), "r")} + , seq_{kseq_init(file_.get())} +{ + // check file handle + if (file_ == nullptr) { + std::ostringstream msg; + msg << "ZmwChunkedFastxTextReader: could not open file for reading\n" + << " file: " << fastxFilename_ << '\n'; + throw std::runtime_error{msg.str()}; + } + + // check kseq sequence handle + assert(seq_ != nullptr); +} + +int ZmwChunkedFastxTextReader::FetchRecord(bool skipName) +{ + // NOTE: kseq_read assumes it is at the beginning of "next" sequence's name. + // However, here the file handle may already point to the first base after + // seeking using FAI. So we optionally load the name. + + int c; + kseq_t* seq = seq_.get(); + kstream_t* ks = seq->f; + seq_->comment.l = seq_->seq.l = seq_->qual.l = 0; /* reset all members */ + + if (!skipName) { + + if (seq->last_char == 0) { /* then jump to the next header line */ + while ((c = ks_getc(ks)) != -1 && c != '>' && c != '@') + ; + if (c == -1) return -1; /* end of file */ + seq->last_char = c; + } /* else: the first header char has been read in the previous call */ + + if (ks_getuntil(ks, 0, &seq->name, &c) < 0) return -1; /* normal exit: EOF */ + if (c != '\n') ks_getuntil(ks, KS_SEP_LINE, &seq->comment, 0); /* read FASTA/Q comment */ + } + + if (seq_->seq.s == 0) { /* we can do this in the loop below, but that is slower */ + seq_->seq.m = 256; + seq_->seq.s = (char*)malloc(seq_->seq.m); + } + while ((c = ks_getc(ks)) != -1 && c != '>' && c != '+' && c != '@') { + if (c == '\n') continue; /* skip empty lines */ + seq_->seq.s[seq_->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ + ks_getuntil2(ks, KS_SEP_LINE, &seq_->seq, 0, 1); /* read the rest of the line */ + } + + if (c == '>' || c == '@') seq_->last_char = c; /* the first header char has been read */ + if (seq_->seq.l + 1 >= + seq_->seq.m) { /* seq_->seq.s[seq_->seq.l] below may be out of boundary */ + seq_->seq.m = seq_->seq.l + 2; + kroundup32(seq_->seq.m); /* rounded to the next closest 2^k */ + seq_->seq.s = (char*)realloc(seq_->seq.s, seq_->seq.m); + } + seq_->seq.s[seq_->seq.l] = 0; /* null terminated string */ + + if (c != '+') return seq_->seq.l; /* FASTA */ + if (seq_->qual.m < seq_->seq.m) { /* allocate memory for qual in case insufficient */ + seq_->qual.m = seq_->seq.m; + seq_->qual.s = (char*)realloc(seq_->qual.s, seq_->qual.m); + } + + while ((c = ks_getc(ks)) != -1 && c != '\n') + ; /* skip the rest of '+' line */ + if (c == -1) return -2; /* error: no quality string */ + while (ks_getuntil2(ks, KS_SEP_LINE, &seq_->qual, 0, 1) >= 0 && seq_->qual.l < seq_->seq.l) + ; + + seq_->last_char = 0; /* we have not come to the next header line */ + + if (seq_->seq.l != seq_->qual.l) return -2; /* error: qual string is of a different length */ + return seq_->seq.l; +} + +int ZmwChunkedFastxTextReader::ReadFromFile(FILE* fp, void* data, size_t length) +{ + return static_cast(std::fread(data, sizeof(uint8_t), length, fp)); +} + +FastaSequence ZmwChunkedFastxTextReader::ReadNextFasta(bool skipName) +{ + // read sequence + const auto result = FetchRecord(skipName); + if (result < 0) { + std::ostringstream msg; + msg << "ZmwChunkedFastxTextReader: error reading from\n" + << " file: " << fastxFilename_ << '\n' + << " reason: likely truncated quality string\n"; + throw std::runtime_error{msg.str()}; + } + + // return FASTQ + std::string name = (skipName ? "" : std::string{seq_->name.s, seq_->name.l}); + std::string bases{seq_->seq.s, seq_->seq.l}; + return FastaSequence{std::move(name), std::move(bases)}; +} + +FastqSequence ZmwChunkedFastxTextReader::ReadNextFastq(bool skipName) +{ + // read sequence + const auto result = FetchRecord(skipName); + if (result < 0) { + std::ostringstream msg; + msg << "ZmwChunkedFastxTextReader: error reading from\n" + << " file: " << fastxFilename_ << '\n' + << " reason: likely truncated quality string\n"; + throw std::runtime_error{msg.str()}; + } + + // return FASTQ + std::string name = (skipName ? "" : std::string{seq_->name.s, seq_->name.l}); + std::string bases{seq_->seq.s, seq_->seq.l}; + Data::QualityValues quals{std::string{seq_->qual.s, seq_->qual.l}}; + return FastqSequence{std::move(name), std::move(bases), std::move(quals)}; +} + +void ZmwChunkedFastxTextReader::Seek(uint64_t pos) +{ + // seek to sequence 'id' & reset kseq handle + auto result = fseek(file_.get(), pos, SEEK_SET); + if (result != 0) { + std::ostringstream msg; + msg << "ZmwChunkedFastxTextReader: could not seek to requested pos: " << pos << '\n' + << " in file: " << fastxFilename_; + throw std::runtime_error{msg.str()}; + } + ks_rewind(seq_->f); +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/ZmwChunkedFastxTextReader.h b/src/ZmwChunkedFastxTextReader.h new file mode 100644 index 0000000..6e91ada --- /dev/null +++ b/src/ZmwChunkedFastxTextReader.h @@ -0,0 +1,59 @@ +// File Description +/// \file ZmwChunkedFastxTextReader.h +/// \brief Defines the ZmwChunkedFastxTextReader class. +// +// Author: Derek Barnett + +#ifndef ZMWCHUNKEDFASTXTEXTREADER_H +#define ZMWCHUNKEDFASTXTEXTREADER_H + +#include "pbbam/Config.h" + +#include "ZmwChunkedFastxReaderImpl.h" + +#include + +#include + +#include +#include + +namespace PacBio { +namespace BAM { + +class ZmwChunkedFastxTextReader final : public ZmwChunkedFastxReaderImpl +{ +public: + ZmwChunkedFastxTextReader(std::string filename, const size_t numChunks); + + void Seek(uint64_t pos) final; + FastaSequence ReadNextFasta(bool skipName) final; + FastqSequence ReadNextFastq(bool skipName) final; + +private: + int FetchRecord(bool getName); + + // kseq needs a '__read' function with this signature, so fread does not work + // in this case. gzread/bgzf_read match but we want better seek performance + // than gzstream and are specifically not using indexed BGZF + static int ReadFromFile(FILE* fp, void* data, size_t length); + + // specialize kseq_t for FILE handle + KSEQ_INIT(FILE*, ReadFromFile) + struct KSeqDeleter + { + void operator()(kseq_t* seq) const + { + if (seq) kseq_destroy(seq); + seq = nullptr; + } + }; + + std::unique_ptr file_; + std::unique_ptr seq_; +}; + +} // namespace BAM +} // namespace PacBio + +#endif // ZMWCHUNKEDFASTXTEXTREADER_H \ No newline at end of file diff --git a/src/ZmwGroupQuery.cpp b/src/ZmwGroupQuery.cpp new file mode 100644 index 0000000..8f89a01 --- /dev/null +++ b/src/ZmwGroupQuery.cpp @@ -0,0 +1,78 @@ +// File Description +/// \file ZmwQuery.cpp +/// \brief Implements the ZmwQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ZmwGroupQuery.h" + +#include +#include +#include + +#include "MemoryUtils.h" +#include "pbbam/BamRecord.h" +#include "pbbam/CompositeBamReader.h" +#include "pbbam/PbiFilterTypes.h" + +namespace PacBio { +namespace BAM { + +class ZmwGroupQuery::ZmwGroupQueryPrivate +{ + using ReaderType = PbiFilterCompositeBamReader; + +public: + ZmwGroupQueryPrivate(const std::vector& zmwWhitelist, const DataSet& dataset) + : whitelist_(zmwWhitelist.cbegin(), zmwWhitelist.cend()) + { + std::sort(whitelist_.begin(), whitelist_.end()); + whitelist_.erase(std::unique(whitelist_.begin(), whitelist_.end()), whitelist_.end()); + + if (!whitelist_.empty()) { + reader_ = std::make_unique(PbiZmwFilter{whitelist_.front()}, dataset); + whitelist_.pop_front(); + } + } + + bool GetNext(std::vector& records) + { + records.clear(); + if (!reader_) return false; + + // get all records matching ZMW + BamRecord r; + while (reader_->GetNext(r)) + records.push_back(r); + + // set next ZMW (if any left) + if (!whitelist_.empty()) { + reader_->Filter(PbiZmwFilter{whitelist_.front()}); + whitelist_.pop_front(); + } + + // otherwise destroy reader, next iteration will return false + else + reader_.reset(); + + return true; + } + +private: + std::deque whitelist_; + std::unique_ptr reader_; +}; + +ZmwGroupQuery::ZmwGroupQuery(const std::vector& zmwWhitelist, const DataSet& dataset) + : internal::IGroupQuery(), d_{std::make_unique(zmwWhitelist, dataset)} +{ +} + +ZmwGroupQuery::~ZmwGroupQuery() = default; + +bool ZmwGroupQuery::GetNext(std::vector& records) { return d_->GetNext(records); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ZmwQuery.cpp b/src/ZmwQuery.cpp new file mode 100644 index 0000000..6048629 --- /dev/null +++ b/src/ZmwQuery.cpp @@ -0,0 +1,40 @@ +// File Description +/// \file ZmwQuery.cpp +/// \brief Implements the ZmwQuery class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ZmwQuery.h" + +#include + +#include "pbbam/CompositeBamReader.h" +#include "pbbam/PbiFilterTypes.h" + +namespace PacBio { +namespace BAM { + +class ZmwQuery::ZmwQueryPrivate +{ +public: + ZmwQueryPrivate(std::vector zmwWhitelist, const DataSet& dataset) + : reader_{PbiZmwFilter{std::move(zmwWhitelist)}, dataset} + { + } + + PbiFilterCompositeBamReader reader_; +}; + +ZmwQuery::ZmwQuery(std::vector zmwWhitelist, const DataSet& dataset) + : internal::IQuery(), d_{std::make_unique(zmwWhitelist, dataset)} +{ +} + +ZmwQuery::~ZmwQuery() = default; + +bool ZmwQuery::GetNext(BamRecord& r) { return d_->reader_.GetNext(r); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ZmwReadStitcher.cpp b/src/ZmwReadStitcher.cpp new file mode 100644 index 0000000..5d018e7 --- /dev/null +++ b/src/ZmwReadStitcher.cpp @@ -0,0 +1,139 @@ +// File Description +/// \file ZmwReadStitcher.cpp +/// \brief Implements the ZmwReadStitcher class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/virtual/ZmwReadStitcher.h" + +#include +#include +#include + +#include "VirtualStitching.h" +#include "VirtualZmwReader.h" +#include "pbbam/DataSet.h" +#include "pbbam/EntireFileQuery.h" +#include "pbbam/PbiFilter.h" +#include "pbbam/PbiFilterQuery.h" + +namespace PacBio { +namespace BAM { + +class ZmwReadStitcher::ZmwReadStitcherPrivate +{ +public: + ZmwReadStitcherPrivate(std::string primaryBamFilePath, std::string scrapsBamFilePath, + PbiFilter filter) + : filter_{std::move(filter)} + { + sources_.push_back({std::move(primaryBamFilePath), std::move(scrapsBamFilePath)}); + OpenNextReader(); + } + + ZmwReadStitcherPrivate(const DataSet& dataset) : filter_{PbiFilter::FromDataSet(dataset)} + { + sources_ = SourcesFromDataset(dataset); + OpenNextReader(); + } + + bool HasNext() const { return (currentReader_ && currentReader_->HasNext()); } + + VirtualZmwBamRecord Next() + { + if (currentReader_) { + const auto result = currentReader_->Next(); + if (!currentReader_->HasNext()) OpenNextReader(); + return result; + } + + // no reader active + throw std::runtime_error{ + "ZmwReadStitcher: " + "no readers active, make sure you use " + "ZmwReadStitcher::HasNext before " + "requesting next record"}; + } + + std::vector NextRaw() + { + if (currentReader_) { + const auto result = currentReader_->NextRaw(); + if (!currentReader_->HasNext()) OpenNextReader(); + return result; + } + + // no reader active + throw std::runtime_error{ + "ZmwReadStitcher: " + "no readers active, make sure you use " + "ZmwReadStitcher::HasNext before " + "requesting next group of records"}; + } + + BamHeader PrimaryHeader() const { return currentReader_->PrimaryHeader(); } + + BamHeader ScrapsHeader() const { return currentReader_->ScrapsHeader(); } + + BamHeader StitchedHeader() const { return currentReader_->StitchedHeader(); } + +private: + StitchingSources sources_; + std::unique_ptr currentReader_; + PbiFilter filter_; + + void OpenNextReader() + { + currentReader_.reset(nullptr); + + // find next source pair with data + while (!sources_.empty()) { + const auto nextSource = sources_.front(); + sources_.pop_front(); + + currentReader_ = + std::make_unique(nextSource.first, nextSource.second, filter_); + if (currentReader_->HasNext()) return; + } + } +}; + +// -------------------------------- +// ZmwReadStitcher implementation +// -------------------------------- + +ZmwReadStitcher::ZmwReadStitcher(std::string primaryBamFilePath, std::string scrapsBamFilePath) + : ZmwReadStitcher{std::move(primaryBamFilePath), std::move(scrapsBamFilePath), PbiFilter{}} +{ +} + +ZmwReadStitcher::ZmwReadStitcher(std::string primaryBamFilePath, std::string scrapsBamFilePath, + PbiFilter filter) + : d_{std::make_unique(std::move(primaryBamFilePath), + std::move(scrapsBamFilePath), std::move(filter))} +{ +} + +ZmwReadStitcher::ZmwReadStitcher(const DataSet& dataset) + : d_{std::make_unique(dataset)} +{ +} + +ZmwReadStitcher::~ZmwReadStitcher() = default; + +bool ZmwReadStitcher::HasNext() { return d_->HasNext(); } + +VirtualZmwBamRecord ZmwReadStitcher::Next() { return d_->Next(); } + +std::vector ZmwReadStitcher::NextRaw() { return d_->NextRaw(); } + +BamHeader ZmwReadStitcher::PrimaryHeader() const { return d_->PrimaryHeader().DeepCopy(); } + +BamHeader ZmwReadStitcher::ScrapsHeader() const { return d_->ScrapsHeader().DeepCopy(); } + +BamHeader ZmwReadStitcher::StitchedHeader() const { return d_->StitchedHeader().DeepCopy(); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ZmwTypeMap.cpp b/src/ZmwTypeMap.cpp new file mode 100644 index 0000000..4c4b5b5 --- /dev/null +++ b/src/ZmwTypeMap.cpp @@ -0,0 +1,25 @@ +// File Description +/// \file ZmwTypeMap.cpp +/// \brief Implements the ZmwTypeMap class. +// +// Author: Armin Töpfer + +#include "PbbamInternalConfig.h" + +#include "pbbam/ZmwTypeMap.h" + +namespace PacBio { +namespace BAM { + +// clang-format off +std::map ZmwTypeMap::ParseChar +{ + { 'C' , ZmwType::CONTROL }, + { 'M' , ZmwType::MALFORMED }, + { 'N' , ZmwType::NORMAL }, + { 'S' , ZmwType::SENTINEL } +}; +// clang-format on + +} // namespace BAM +} // namespace PacBio diff --git a/src/bed/BedReader.cpp b/src/bed/BedReader.cpp new file mode 100644 index 0000000..2f4391e --- /dev/null +++ b/src/bed/BedReader.cpp @@ -0,0 +1,117 @@ +// File Description +/// \file BedReader.cpp +/// \brief Implements the BedReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/bed/BedReader.h" + +#include + +#include +#include +#include + +#include +#include + +#include "pbbam/FormatUtils.h" +#include "pbbam/StringUtilities.h" +#include "pbbam/TextFileReader.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "BedReader(const BedReader&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "BedReader& operator=(const BedReader&) is not = delete"); + +class BedReader::BedReaderPrivate +{ +public: + explicit BedReaderPrivate(const std::string& fn) + { + // validate extension + if (!FormatUtils::IsBedFilename(fn)) { + throw std::runtime_error{"BedReader ERROR: filename '" + fn + + "' is not recognized as a BED file."}; + } + + // open file stream + reader_ = std::make_unique(fn); + if (!reader_) { + throw std::runtime_error("BedReader ERROR: could not open text file '" + fn + + "' for reading"); + } + + // pre-fetch first record + GetNext(); + } + + void GetNext() + { + interval_ = boost::none; + std::string line; + if (reader_->GetNext(line)) interval_ = ParseInterval(std::move(line)); + } + + GenomicInterval ParseInterval(std::string line) + { + // trim any trailing whitespace + boost::trim_right(line); + + // split into token fields + const auto fields = PacBio::BAM::Split(line, '\t'); + if (fields.size() < 3) { + std::ostringstream msg; + msg << "BedReader ERROR: invalid BED record. Line:\n" + << line << '\n' + << "has less than 3 fields."; + throw std::runtime_error{msg.str()}; + } + + // convert fields into interval + const Position start = std::stoi(fields[1]); + const Position end = std::stoi(fields[2]); + return {fields[0], start, end}; + } + + std::unique_ptr reader_; + boost::optional interval_; +}; + +BedReader::BedReader(const std::string& fn) + : internal::QueryBase{}, d_{std::make_unique(fn)} +{ +} + +BedReader::BedReader(BedReader&&) noexcept = default; + +BedReader& BedReader::operator=(BedReader&&) noexcept = default; + +BedReader::~BedReader() = default; + +bool BedReader::GetNext(GenomicInterval& interval) +{ + if (!d_->interval_) return false; + + interval = *d_->interval_; + d_->GetNext(); + return true; +} + +std::vector BedReader::ReadAll(const std::string& fn) +{ + std::vector result; + result.reserve(256); + BedReader reader{fn}; + for (const auto& seq : reader) + result.emplace_back(seq); + return result; +} + +} // namespace BAM +} // namespace PacBio diff --git a/src/bed/BedWriter.cpp b/src/bed/BedWriter.cpp new file mode 100644 index 0000000..c74919d --- /dev/null +++ b/src/bed/BedWriter.cpp @@ -0,0 +1,55 @@ +// File Description +/// \file BedWriter.cpp +/// \brief Implements the BedWriter class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/bed/BedWriter.h" + +#include + +#include +#include + +#include "pbbam/GenomicInterval.h" +#include "pbbam/TextFileWriter.h" + +namespace PacBio { +namespace BAM { + +static_assert(!std::is_copy_constructible::value, + "BedWriter(const BedWriter&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "BedWriter& operator=(const BedWriter&) is not = delete"); + +class BedWriter::BedWriterPrivate +{ +public: + explicit BedWriterPrivate(const std::string& filename) : writer_{filename} {} + + void Write(const GenomicInterval& interval) + { + line_.str(""); + line_ << interval.Name() << '\t' << interval.Start() << '\t' << interval.Stop(); + writer_.Write(line_.str()); + } + +private: + std::ostringstream line_; + TextFileWriter writer_; +}; + +BedWriter::BedWriter(const std::string& fn) : d_{std::make_unique(fn)} {} + +BedWriter::BedWriter(BedWriter&&) noexcept = default; + +BedWriter& BedWriter::operator=(BedWriter&&) noexcept = default; + +BedWriter::~BedWriter() = default; + +void BedWriter::Write(const GenomicInterval& interval) { d_->Write(interval); } + +} // namespace BAM +} // namespace PacBio diff --git a/src/ccs/CCSPbiBuilder.cpp b/src/ccs/CCSPbiBuilder.cpp new file mode 100644 index 0000000..db45d8d --- /dev/null +++ b/src/ccs/CCSPbiBuilder.cpp @@ -0,0 +1,330 @@ +// File Description +/// \file CCSPbiBuilder.cpp +/// \brief Implements the CCSPbiBuilder.cpp class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ccs/CCSPbiBuilder.h" + +#include +#include + +#include +#include +#include + +#include +#include + +#include "pbbam/PbiBuilder.h" +#include "pbbam/PbiFile.h" +#include "pbbam/ccs/CCSHeader.h" +#include "pbbam/ccs/CCSRecord.h" + +#include "MemoryUtils.h" + +namespace PacBio { +namespace CCS { +namespace internal { + +template +inline void SwapEndianness(std::vector& data) +{ + const size_t elementSize = sizeof(T); + const size_t numReads = data.size(); + switch (elementSize) { + case 1: + break; // no swapping necessary + case 2: + for (size_t i = 0; i < numReads; ++i) + ed_swap_2p(&data[i]); + break; + case 4: + for (size_t i = 0; i < numReads; ++i) + ed_swap_4p(&data[i]); + break; + case 8: + for (size_t i = 0; i < numReads; ++i) + ed_swap_8p(&data[i]); + break; + default: + throw std::runtime_error{"CCSPbiBuilder: unsupported element size (" + + std::to_string(elementSize) + ")"}; + } +} + +void bgzf_write_safe(BGZF* fp, const void* data, size_t length) +{ + const auto ret = bgzf_write(fp, data, length); + if (ret < 0L) + throw std::runtime_error{ + "CCSPbiBuilder: non-zero returned from bgzf_write(). Out of disk space?"}; +} + +template +inline void WriteBgzfVector(BGZF* fp, std::vector& data) +{ + assert(fp); + if (fp->is_be) SwapEndianness(data); + bgzf_write_safe(fp, &data[0], data.size() * sizeof(T)); +} + +struct PbiFieldBlock +{ + int64_t pos_; // file position of block start + size_t n_; // number of entries in block +}; + +template +class PbiField +{ + constexpr static const size_t ElementSize = sizeof(T); + +public: + PbiField(size_t maxBufferSize) : maxElementCount_{maxBufferSize / ElementSize} + { + buffer_.reserve(maxElementCount_); + } + + void Add(T value) { buffer_.push_back(value); } + bool IsFull() const { return buffer_.size() == maxElementCount_; } + + size_t maxElementCount_; + std::vector buffer_; + std::vector blocks_; +}; + +} // namespace internal + +class CCSPbiBuilder::CCSPbiBuilderPrivate +{ + enum class FlushMode + { + FORCE, + NO_FORCE + }; + + // TODO: Make this tweak-able, a la IndexedBamWriter's buffers + constexpr static const size_t MaxBufferSize = 0x10000; + +public: + CCSPbiBuilderPrivate(const std::string& pbiFilename, const std::string& movieName, + const CCSPbiBuilderConfig& config) + : pbiFilename_{pbiFilename} + , tempFilename_{pbiFilename + ".build"} + , tempFile_{std::fopen(tempFilename_.c_str(), "w+b")} + , compressionLevel_{config.CompressionLevel} + , numThreads_{config.NumThreads} + , rgIdField_{MaxBufferSize} + , qStartField_{MaxBufferSize} + , qEndField_{MaxBufferSize} + , holeNumField_{MaxBufferSize} + , readQualField_{MaxBufferSize} + , ctxtField_{MaxBufferSize} + , fileOffsetField_{MaxBufferSize} + { + movieName_ = movieName; + rgId_ = BAM::ReadGroupInfo::IdToInt(BAM::MakeReadGroupId(movieName, "SUBREAD")); + } + + void AddRecord(const CCSRecord& record) + { + rgIdField_.Add(rgId_); + qStartField_.Add(record.QueryStart); + qEndField_.Add(record.QueryEnd); + holeNumField_.Add(record.HoleNumber); + ctxtField_.Add(record.LocalContextFlags); + readQualField_.Add(record.Accuracy); + fileOffsetField_.Add(-1); + + FlushBuffers(FlushMode::NO_FORCE); + ++currentRow_; + } + + void Close() + { + if (isClosed_) return; + + FlushBuffers(FlushMode::FORCE); + + OpenPbiFile(); + WritePbiHeader(); + WriteFromTempFile(); + + std::remove(tempFilename_.c_str()); + isClosed_ = true; + } + + template + void MaybeFlushBuffer(internal::PbiField& field, bool force) + { + // replace with lambda, in FlushBuffer(), once PPA can use C++14 ? + if (field.IsFull() || force) { + WriteToTempFile(field); + field.buffer_.clear(); + } + } + + void FlushBuffers(FlushMode mode) + { + const auto force = (mode == FlushMode::FORCE); + MaybeFlushBuffer(rgIdField_, force); + MaybeFlushBuffer(qStartField_, force); + MaybeFlushBuffer(qEndField_, force); + MaybeFlushBuffer(holeNumField_, force); + MaybeFlushBuffer(readQualField_, force); + MaybeFlushBuffer(ctxtField_, force); + MaybeFlushBuffer(fileOffsetField_, force); + } + + template + void WriteToTempFile(internal::PbiField& field) + { + if (field.buffer_.empty()) return; + + const auto pos = std::ftell(tempFile_.get()); + const auto numElements = + std::fwrite(field.buffer_.data(), sizeof(T), field.buffer_.size(), tempFile_.get()); + field.blocks_.emplace_back(internal::PbiFieldBlock{pos, numElements}); + } + + void OpenPbiFile() + { + // open file handle + const auto mode = std::string("wb") + std::to_string(static_cast(compressionLevel_)); + pbiFile_.reset(bgzf_open(pbiFilename_.c_str(), mode.c_str())); + if (pbiFile_ == nullptr) + throw std::runtime_error{"CCSPbiBuilder: could not open file for writing: " + + pbiFilename_}; + + // if no explicit thread count given, attempt built-in check + size_t actualNumThreads = numThreads_; + if (actualNumThreads == 0) { + actualNumThreads = std::thread::hardware_concurrency(); + + // if still unknown, default to single-threaded + if (actualNumThreads == 0) actualNumThreads = 1; + } + + // if multithreading requested, enable it + if (actualNumThreads > 1) bgzf_mt(pbiFile_.get(), actualNumThreads, 256); + } + + void WritePbiHeader() + { + BGZF* bgzf = pbiFile_.get(); + + // 'magic' string + static constexpr const std::array magic{{'P', 'B', 'I', '\1'}}; + internal::bgzf_write_safe(bgzf, magic.data(), 4); + + PacBio::BAM::PbiFile::Sections sections = PacBio::BAM::PbiFile::BASIC; + // version, pbi_flags, & n_reads + auto version = static_cast(PacBio::BAM::PbiFile::CurrentVersion); + uint16_t pbi_flags = sections; + auto numReads = currentRow_; + if (bgzf->is_be) { + version = ed_swap_4(version); + pbi_flags = ed_swap_2(pbi_flags); + numReads = ed_swap_4(numReads); + } + internal::bgzf_write_safe(bgzf, &version, 4); + internal::bgzf_write_safe(bgzf, &pbi_flags, 2); + internal::bgzf_write_safe(bgzf, &numReads, 4); + + // reserved space + char reserved[18]; + memset(reserved, 0, 18); + internal::bgzf_write_safe(bgzf, reserved, 18); + } + + template + void LoadFieldBlockFromTempFile(internal::PbiField& field, + const internal::PbiFieldBlock& block) + { + // seek to block begin + const auto ret = std::fseek(tempFile_.get(), block.pos_, SEEK_SET); + if (ret != 0) + throw std::runtime_error{"CCSPbiBuilder: could not seek in temp file: " + + tempFilename_ + ", offset: " + std::to_string(block.pos_)}; + + // read block elements + field.buffer_.assign(block.n_, 0); + const auto numElements = + std::fread(field.buffer_.data(), sizeof(T), block.n_, tempFile_.get()); + + if (numElements != block.n_) + throw std::runtime_error{ + "CCSPbiBuilder: could not read element count from temp file: " + tempFilename_}; + } + + template + void WriteField(internal::PbiField& field) + { + for (const auto& block : field.blocks_) { + LoadFieldBlockFromTempFile(field, block); + internal::WriteBgzfVector(pbiFile_.get(), field.buffer_); + } + } + + void WriteFromTempFile() + { + // load from temp file, in PBI format order, and write to index + WriteField(rgIdField_); + WriteField(qStartField_); + WriteField(qEndField_); + WriteField(holeNumField_); + WriteField(readQualField_); + WriteField(ctxtField_); + WriteField(fileOffsetField_); + } + + // file info + std::string bamFilename_; + std::string pbiFilename_; + std::string tempFilename_; + std::unique_ptr tempFile_; + std::unique_ptr pbiFile_; + PacBio::BAM::PbiBuilder::CompressionLevel compressionLevel_ = + PacBio::BAM::PbiBuilder::DefaultCompression; + size_t numThreads_; + + // PBI field buffers + internal::PbiField rgIdField_; + internal::PbiField qStartField_; + internal::PbiField qEndField_; + internal::PbiField holeNumField_; + internal::PbiField readQualField_; + internal::PbiField ctxtField_; + internal::PbiField fileOffsetField_; + + std::string movieName_; + int32_t rgId_; + uint32_t currentRow_ = 0; + bool isClosed_ = false; +}; + +CCSPbiBuilder::CCSPbiBuilder(const std::string& pbiFilename, const std::string& movieName, + const CCSPbiBuilderConfig& config) + : d_{std::make_unique(pbiFilename, movieName, config)} +{ +} + +CCSPbiBuilder::CCSPbiBuilder(const std::string& pbiFilename, const CCSHeader& header, + const CCSPbiBuilderConfig& config) + : CCSPbiBuilder{pbiFilename, header.MovieName, config} +{ +} + +CCSPbiBuilder::~CCSPbiBuilder() = default; + +void CCSPbiBuilder::AddRecord(const CCSRecord& record) { d_->AddRecord(record); } + +void CCSPbiBuilder::Close() { d_->Close(); } + +const std::string& CCSPbiBuilder::MovieName() const { return d_->movieName_; } + +} // namespace CCS +} // namespace PacBio \ No newline at end of file diff --git a/src/ccs/CCSRecordFormat.cpp b/src/ccs/CCSRecordFormat.cpp new file mode 100644 index 0000000..4abfb5a --- /dev/null +++ b/src/ccs/CCSRecordFormat.cpp @@ -0,0 +1,144 @@ +// File Description +/// \file CCSRecordFormat.cpp +/// \brief Implements the CCSRecordFormat class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ccs/CCSRecordFormat.h" + +#include +#include +#include + +#include "pbbam/StringUtilities.h" + +namespace { + +static const std::string MovieName{"movie_name"}; +static const std::string BindingKit{"binding_kit"}; +static const std::string SequencingKit{"sequencing_kit"}; +static const std::string BasecallerVersion{"basecaller_version"}; +static const std::string FrameRate{"framerate"}; + +} // namespace + +namespace PacBio { +namespace CCS { + +CCSHeader CCSRecordFormat::DeserializeHeader(const std::vector& lines) +{ + if (lines.empty()) + throw std::runtime_error{"CCS record format: cannot create header from empty text"}; + + CCSHeader result; + std::vector fields; + for (const auto& line : lines) { + fields = PacBio::BAM::Split(line, '='); + if (fields.size() != 2) { + std::ostringstream msg; + msg << "CCS record format: malformatted header line\n" + << line << '\n' + << "must have syntax 'name=value'"; + throw std::runtime_error{msg.str()}; + } + + // clang-format off + if (fields[0] == MovieName) result.MovieName = fields[1]; + else if (fields[0] == BindingKit) result.BindingKit = fields[1]; + else if (fields[0] == SequencingKit) result.SequencingKit = fields[1]; + else if (fields[0] == BasecallerVersion) result.BasecallerVersion = fields[1]; + else if (fields[0] == FrameRate) result.FrameRate = fields[1]; + else { + std::ostringstream msg; + msg << "CCS record format: unrecognized header field name: '" << fields[0] << '\''; + throw std::runtime_error{msg.str()}; + } + // clang-format on + } + return result; +} + +std::vector CCSRecordFormat::SerializeHeader(const CCSHeader& header) +{ + // clang-format off + std::vector result; + result.push_back(MovieName + '=' + header.MovieName); + result.push_back(BindingKit + '=' + header.BindingKit); + result.push_back(SequencingKit + '=' + header.SequencingKit); + result.push_back(BasecallerVersion + '=' + header.BasecallerVersion); + result.push_back(FrameRate + '=' + header.FrameRate); + // clang-format on + return result; +} + +CCSRecord CCSRecordFormat::DeserializeRecord(const std::string& line) +{ + const auto fields = PacBio::BAM::Split(line); + if (fields.size() != 8) { + std::ostringstream msg; + msg << "CCS record format: malformatted record line\n" << line << '\n'; + throw std::runtime_error{msg.str()}; + } + + // clang-format off + CCSRecord result; + result.HoleNumber = std::stoi(fields[0]); + result.QueryStart = std::stoi(fields[1]); + result.QueryEnd = std::stoi(fields[2]); + result.LocalContextFlags = static_cast(std::stoul(fields[3])); + result.Accuracy = std::stof(fields[4]); + + const auto snrs = PacBio::BAM::Split(fields[5], ','); + if (snrs.size() != 4) { + std::ostringstream msg; + msg << "CCS record format: SNR field must have 4 values"; + throw std::runtime_error{msg.str()}; + } + result.SignalToNoise = { + std::stod(snrs[0]), + std::stod(snrs[1]), + std::stod(snrs[2]), + std::stod(snrs[3]) + }; + + result.Sequence = fields[6]; + + const auto pwStrings = PacBio::BAM::Split(fields[7], ','); + std::vector pws; + pws.reserve(pwStrings.size()); + for (const auto& pwString : pwStrings) + pws.emplace_back(std::stoul(pwString)); + result.PulseWidths = pws; + + // clang-format on + return result; +} + +std::string CCSRecordFormat::SerializeRecord(const CCSRecord& record) +{ + // clang-format off + std::ostringstream out; + out << record.HoleNumber << '\t' + << record.QueryStart << '\t' + << record.QueryEnd << '\t' + << static_cast(record.LocalContextFlags) << '\t' + << record.Accuracy << '\t' + << record.SignalToNoise.A << ',' << record.SignalToNoise.C << ',' + << record.SignalToNoise.G << ',' << record.SignalToNoise.T << '\t' + << record.Sequence << '\t'; + + bool first = true; + for (const auto pw : record.PulseWidths) { + if (!first) out << ','; + else first = false; + out << pw; + } + + // clang-format on + return out.str(); +} + +} // namespace CCS +} // namespace PacBio \ No newline at end of file diff --git a/src/ccs/CCSRecordReader.cpp b/src/ccs/CCSRecordReader.cpp new file mode 100644 index 0000000..efeee63 --- /dev/null +++ b/src/ccs/CCSRecordReader.cpp @@ -0,0 +1,65 @@ +// File Description +/// \file CCSRecordReader.cpp +/// \brief Implements the CCSRecordReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ccs/CCSRecordReader.h" + +#include +#include +#include +#include + +#include "pbbam/ccs/CCSRecordFormat.h" + +namespace PacBio { +namespace CCS { + +class CCSRecordReader::CCSRecordReaderPrivate +{ +public: + CCSRecordReaderPrivate(std::istream& in) : in_{in} { ReadHeader(); } + + void ReadHeader() + { + const std::string EndHeader{"#"}; + + std::vector lines; + std::string line; + while (std::getline(in_, line)) { + if (line == EndHeader) break; + lines.push_back(line); + } + header_ = CCSRecordFormat::DeserializeHeader(lines); + } + + bool GetNext(CCSRecord& record) + { + if (!std::getline(in_, line_)) return false; // indicates EOF + record = CCSRecordFormat::DeserializeRecord(line_); + return true; + } + + std::istream& in_; + std::string line_; + CCSHeader header_; +}; + +CCSRecordReader::CCSRecordReader() : CCSRecordReader{std::cin} {} + +CCSRecordReader::CCSRecordReader(std::istream& in) + : d_{std::make_unique(in)} +{ +} + +CCSRecordReader::~CCSRecordReader() = default; + +bool CCSRecordReader::GetNext(CCSRecord& record) { return d_->GetNext(record); } + +const CCSHeader& CCSRecordReader::Header() const { return d_->header_; } + +} // namespace CCS +} // namespace PacBio \ No newline at end of file diff --git a/src/ccs/CCSRecordWriter.cpp b/src/ccs/CCSRecordWriter.cpp new file mode 100644 index 0000000..32b0a02 --- /dev/null +++ b/src/ccs/CCSRecordWriter.cpp @@ -0,0 +1,56 @@ +// File Description +/// \file CCSRecordReader.cpp +/// \brief Implements the CCSRecordReader class. +// +// Author: Derek Barnett + +#include "PbbamInternalConfig.h" + +#include "pbbam/ccs/CCSRecordWriter.h" + +#include +#include +#include + +#include "pbbam/ccs/CCSRecordFormat.h" + +namespace PacBio { +namespace CCS { + +class CCSRecordWriter::CCSRecordWriterPrivate +{ +public: + CCSRecordWriterPrivate(const CCSHeader& header, std::ostream& out) : out_{out} + { + WriteHeader(header); + } + + void WriteHeader(const CCSHeader& header) + { + const auto lines = CCSRecordFormat::SerializeHeader(header); + for (const auto& line : lines) + out_ << line << '\n'; + out_ << "#\n"; + } + + void Write(const CCSRecord& record) + { + out_ << CCSRecordFormat::SerializeRecord(record) << '\n'; + } + + std::ostream& out_; +}; + +CCSRecordWriter::CCSRecordWriter(const CCSHeader& header) : CCSRecordWriter{header, std::cout} {} + +CCSRecordWriter::CCSRecordWriter(const CCSHeader& header, std::ostream& out) + : d_{std::make_unique(header, out)} +{ +} + +CCSRecordWriter::~CCSRecordWriter() = default; + +void CCSRecordWriter::Write(const CCSRecord& record) { d_->Write(record); } + +} // namespace CCS +} // namespace PacBio \ No newline at end of file diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..4c3b104 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,153 @@ +########### +# sources # +########### + +pbbam_cpp_sources = files([ + 'AlignmentPrinter.cpp', + 'BaiIndexCache.cpp', + 'BaiIndexedBamReader.cpp', + 'BamFile.cpp', + 'BamFileMerger.cpp', + 'BamHeader.cpp', + 'BamReader.cpp', + 'BamRecord.cpp', + 'BamRecordBuilder.cpp', + 'BamRecordImpl.cpp', + 'BamRecordTags.cpp', + 'BamRecordView.cpp', + 'BamTagCodec.cpp', + 'BamWriter.cpp', + 'BarcodeQuery.cpp', + 'BgzipFastaWriter.cpp', + 'BgzipFastqWriter.cpp', + 'BgzipWriter.cpp', + 'ChemistryTable.cpp', + 'Compare.cpp', + 'CompositeFastaReader.cpp', + 'Config.cpp', + 'DataSet.cpp', + 'DataSetBaseTypes.cpp', + 'DataSetElement.cpp', + 'DataSetIO.cpp', + 'DataSetTypes.cpp', + 'DataSetXsd.cpp', + 'EntireFileQuery.cpp', + 'FaiIndex.cpp', + 'FaiZmwChunker.cpp', + 'FastaCache.cpp', + 'FastaReader.cpp', + 'FastaSequence.cpp', + 'FastaSequenceQuery.cpp', + 'FastaWriter.cpp', + 'FastqReader.cpp', + 'FastqSequence.cpp', + 'FastqWriter.cpp', + 'FileProducer.cpp', + 'FileUtils.cpp', + 'FofnReader.cpp', + 'FormatUtils.cpp', + 'GenomicIntervalQuery.cpp', + 'IFastaWriter.cpp', + 'IFastqWriter.cpp', + 'IndexedBamWriter.cpp', + 'IndexedFastaReader.cpp', + 'IndexedFastqBgzfReader.cpp', + 'IndexedFastqReader.cpp', + 'IndexedFastqTextReader.cpp', + 'IndexedFastqReaderImpl.cpp', + 'IRecordWriter.cpp', + 'KSeqReader.cpp', + 'MD5.cpp', + 'MemoryUtils.cpp', + 'PbiBuilder.cpp', + 'PbiFile.cpp', + 'PbiFilter.cpp', + 'PbiFilterQuery.cpp', + 'PbiFilterTypes.cpp', + 'PbiIndexedBamReader.cpp', + 'PbiIndexIO.cpp', + 'PbiRawData.cpp', + 'ProgramInfo.cpp', + 'QNameQuery.cpp', + 'ReadAccuracyQuery.cpp', + 'ReadGroupInfo.cpp', + 'RecordType.cpp', + 'SamTagCodec.cpp', + 'SamWriter.cpp', + 'SequenceInfo.cpp', + 'StringUtilities.cpp', + 'SubreadLengthQuery.cpp', + 'Tag.cpp', + 'TagCollection.cpp', + 'TextFileReader.cpp', + 'TextFileWriter.cpp', + 'Validator.cpp', + 'ValidationErrors.cpp', + 'ValidationException.cpp', + 'Version.cpp', + 'VirtualZmwBamRecord.cpp', + 'VirtualZmwCompositeReader.cpp', + 'VirtualZmwReader.cpp', + 'VirtualRegion.cpp', + 'VirtualRegionTypeMap.cpp', + 'XmlReader.cpp', + 'XmlWriter.cpp', + 'WhitelistedZmwReadStitcher.cpp', + 'ZmwChunkedFastaReader.cpp', + 'ZmwChunkedFastqReader.cpp', + 'ZmwChunkedFastxBgzfReader.cpp', + 'ZmwChunkedFastxReaderImpl.cpp', + 'ZmwChunkedFastxTextReader.cpp', + 'ZmwGroupQuery.cpp', + 'ZmwReadStitcher.cpp', + 'ZmwQuery.cpp', + 'ZmwTypeMap.cpp', + + # bed + 'bed/BedReader.cpp', + 'bed/BedWriter.cpp', + + # ccs + 'ccs/CCSPbiBuilder.cpp', + 'ccs/CCSRecordFormat.cpp', + 'ccs/CCSRecordReader.cpp', + 'ccs/CCSRecordWriter.cpp', + + # vcf + 'vcf/VcfFile.cpp', + 'vcf/VcfFormat.cpp', + 'vcf/VcfHeader.cpp', + 'vcf/VcfHeaderTypes.cpp', + 'vcf/VcfQuery.cpp', + 'vcf/VcfReader.cpp', + 'vcf/VcfSort.cpp', + 'vcf/VcfVariant.cpp', + 'vcf/VcfWriter.cpp', + + # XML I/O + 'pugixml/pugixml.cpp' +]) + +pbbam_extra_flags = [] +if get_option('auto-validate') + pbbam_extra_flags += '-DPBBAM_AUTOVALIDATE=1' +endif + +# install library if +# - either running as a proper project +# - or using shared libraries +pbbam_lib_install = (not meson.is_subproject()) or (get_option('default_library') == 'shared') + +pbbam_lib = library( + 'pbbam', + pbbam_cpp_sources, + # use boost SONAME practice: + # cause ld startup issues before + # you even have the chance of running + # into ABI issues. + soversion : meson.project_version(), + version : meson.project_version(), + install : pbbam_lib_install, + dependencies : [pbbam_thread_dep, pbbam_boost_dep, pbbam_zlib_dep, pbbam_htslib_dep, pbbam_pbcopper_dep], + include_directories : pbbam_include_directories, + cpp_args : [pbbam_extra_flags, pbbam_warning_flags, pbbam_macros]) diff --git a/src/pugixml/pugiconfig.hpp b/src/pugixml/pugiconfig.hpp new file mode 100644 index 0000000..6219dbe --- /dev/null +++ b/src/pugixml/pugiconfig.hpp @@ -0,0 +1,71 @@ +/** + * pugixml parser - version 1.5 + * -------------------------------------------------------- + * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at http://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef HEADER_PUGICONFIG_HPP +#define HEADER_PUGICONFIG_HPP + +// Uncomment this to enable wchar_t mode +// #define PUGIXML_WCHAR_MODE + +// Uncomment this to disable XPath +// #define PUGIXML_NO_XPATH + +// Uncomment this to disable STL +// #define PUGIXML_NO_STL + +// Uncomment this to disable exceptions +// #define PUGIXML_NO_EXCEPTIONS + +// Set this to control attributes for public classes/functions, i.e.: +// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL +// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL +// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall +// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead + +// Tune these constants to adjust memory-related behavior +// #define PUGIXML_MEMORY_PAGE_SIZE 32768 +// #define PUGIXML_MEMORY_OUTPUT_STACK 10240 +// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 + +// Uncomment this to switch to header-only version +// #define PUGIXML_HEADER_ONLY + +// Uncomment this to enable long long support +// #define PUGIXML_HAS_LONG_LONG + +#endif + +/** + * Copyright (c) 2006-2014 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/src/pugixml/pugixml.cpp b/src/pugixml/pugixml.cpp new file mode 100644 index 0000000..37bdec0 --- /dev/null +++ b/src/pugixml/pugixml.cpp @@ -0,0 +1,11539 @@ +/** + * pugixml parser - version 1.5 + * -------------------------------------------------------- + * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at http://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef SOURCE_PUGIXML_CPP +#define SOURCE_PUGIXML_CPP + +// disable all the warnings in this file +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdouble-promotion" + +#if __GNUC__ >= 6 +#pragma GCC diagnostic ignored "-Wnull-dereference" +#endif + +#if !defined(__clang__) and !defined(__INTEL_COMPILER) +#pragma GCC diagnostic ignored "-Wuseless-cast" +#endif + +#include "../PbbamInternalConfig.h" + +#include "pugixml.hpp" + +#include +#include +#include +#include +#include +#include + +#ifdef PUGIXML_WCHAR_MODE +# include +#endif + +#ifndef PUGIXML_NO_XPATH +# include +# include +# ifdef PUGIXML_NO_EXCEPTIONS +# include +# endif +#endif + +#ifndef PUGIXML_NO_STL +# include +# include +# include +#endif + +// For placement new +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +# pragma warning(disable: 4611) // interaction between '_setjmp' and C++ object destruction is non-portable +# pragma warning(disable: 4702) // unreachable code +# pragma warning(disable: 4996) // this function or variable may be unsafe +# pragma warning(disable: 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged +#endif + +#ifdef __INTEL_COMPILER +# pragma warning(disable: 177) // function was declared but never referenced +# pragma warning(disable: 279) // controlling expression is constant +# pragma warning(disable: 1478 1786) // function was declared "deprecated" +# pragma warning(disable: 1684) // conversion from pointer to same-sized integral type +#endif + +#if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY) +# pragma warn -8080 // symbol is declared but never used; disabling this inside push/pop bracket does not make the warning go away +#endif + +#ifdef __BORLANDC__ +# pragma option push +# pragma warn -8008 // condition is always false +# pragma warn -8066 // unreachable code +#endif + +#ifdef __SNC__ +// Using diag_push/diag_pop does not disable the warnings inside templates due to a compiler bug +# pragma diag_suppress=178 // function was declared but never referenced +# pragma diag_suppress=237 // controlling expression is constant +#endif + +// Inlining controls +#if defined(_MSC_VER) && _MSC_VER >= 1300 +# define PUGI__NO_INLINE __declspec(noinline) +#elif defined(__GNUC__) +# define PUGI__NO_INLINE __attribute__((noinline)) +#else +# define PUGI__NO_INLINE +#endif + +// Branch weight controls +#if defined(__GNUC__) +# define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0) +#else +# define PUGI__UNLIKELY(cond) (cond) +#endif + +// Simple static assertion +#define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; } + +// Digital Mars C++ bug workaround for passing char loaded from memory via stack +#ifdef __DMC__ +# define PUGI__DMC_VOLATILE volatile +#else +# define PUGI__DMC_VOLATILE +#endif + +// Borland C++ bug workaround for not defining ::memcpy depending on header include order (can't always use std::memcpy because some compilers don't have it at all) +#if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST) +using std::memcpy; +using std::memmove; +#endif + +// In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features +#if defined(_MSC_VER) && !defined(__S3E__) +# define PUGI__MSVC_CRT_VERSION _MSC_VER +#endif + +#ifdef PUGIXML_HEADER_ONLY +# define PUGI__NS_BEGIN namespace pugi { namespace impl { +# define PUGI__NS_END } } +# define PUGI__FN inline +# define PUGI__FN_NO_INLINE inline +#else +# if defined(_MSC_VER) && _MSC_VER < 1300 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces +# define PUGI__NS_BEGIN namespace pugi { namespace impl { +# define PUGI__NS_END } } +# else +# define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace { +# define PUGI__NS_END } } } +# endif +# define PUGI__FN +# define PUGI__FN_NO_INLINE PUGI__NO_INLINE +#endif + +// uintptr_t +#if !defined(_MSC_VER) || _MSC_VER >= 1600 +# include +#else +# ifndef _UINTPTR_T_DEFINED +// No native uintptr_t in MSVC6 and in some WinCE versions +typedef size_t uintptr_t; +#define _UINTPTR_T_DEFINED +# endif +PUGI__NS_BEGIN + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +PUGI__NS_END +#endif + +// Memory allocation +PUGI__NS_BEGIN + PUGI__FN void* default_allocate(size_t size) + { + return malloc(size); + } + + PUGI__FN void default_deallocate(void* ptr) + { + free(ptr); + } + + template + struct xml_memory_management_function_storage + { + static allocation_function allocate; + static deallocation_function deallocate; + }; + + // Global allocation functions are stored in class statics so that in header mode linker deduplicates them + // Without a template<> we'll get multiple definitions of the same static + template allocation_function xml_memory_management_function_storage::allocate = default_allocate; + template deallocation_function xml_memory_management_function_storage::deallocate = default_deallocate; + + typedef xml_memory_management_function_storage xml_memory; +PUGI__NS_END + +// String utilities +PUGI__NS_BEGIN + // Get string length + PUGI__FN size_t strlength(const char_t* s) + { + assert(s); + + #ifdef PUGIXML_WCHAR_MODE + return wcslen(s); + #else + return strlen(s); + #endif + } + + // Compare two strings + PUGI__FN bool strequal(const char_t* src, const char_t* dst) + { + assert(src && dst); + + #ifdef PUGIXML_WCHAR_MODE + return wcscmp(src, dst) == 0; + #else + return strcmp(src, dst) == 0; + #endif + } + + // Compare lhs with [rhs_begin, rhs_end) + PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) + { + for (size_t i = 0; i < count; ++i) + if (lhs[i] != rhs[i]) + return false; + + return lhs[count] == 0; + } + + // Get length of wide string, even if CRT lacks wide character support + PUGI__FN size_t strlength_wide(const wchar_t* s) + { + assert(s); + + #ifdef PUGIXML_WCHAR_MODE + return wcslen(s); + #else + const wchar_t* end = s; + while (*end) end++; + return static_cast(end - s); + #endif + } + +#ifdef PUGIXML_WCHAR_MODE + // Convert string to wide string, assuming all symbols are ASCII + PUGI__FN void widen_ascii(wchar_t* dest, const char* source) + { + for (const char* i = source; *i; ++i) *dest++ = *i; + *dest = 0; + } +#endif +PUGI__NS_END + +#if !defined(PUGIXML_NO_STL) || !defined(PUGIXML_NO_XPATH) +// auto_ptr-like buffer holder for exception recovery +PUGI__NS_BEGIN + struct buffer_holder + { + void* data; + void (*deleter)(void*); + + buffer_holder(void* data_, void (*deleter_)(void*)): data(data_), deleter(deleter_) + { + } + + ~buffer_holder() + { + if (data) deleter(data); + } + + void* release() + { + void* result = data; + data = 0; + return result; + } + }; +PUGI__NS_END +#endif + +PUGI__NS_BEGIN + static const size_t xml_memory_page_size = + #ifdef PUGIXML_MEMORY_PAGE_SIZE + PUGIXML_MEMORY_PAGE_SIZE + #else + 32768 + #endif + ; + + static const uintptr_t xml_memory_page_alignment = 64; + static const uintptr_t xml_memory_page_pointer_mask = ~(xml_memory_page_alignment - 1); + static const uintptr_t xml_memory_page_contents_shared_mask = 32; + static const uintptr_t xml_memory_page_name_allocated_mask = 16; + static const uintptr_t xml_memory_page_value_allocated_mask = 8; + static const uintptr_t xml_memory_page_type_mask = 7; + static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask; + static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask; + + #define PUGI__NODETYPE(n) static_cast(((n)->header & impl::xml_memory_page_type_mask) + 1) + + struct xml_allocator; + + struct xml_memory_page + { + static xml_memory_page* construct(void* memory) + { + xml_memory_page* result = static_cast(memory); + + result->allocator = 0; + result->prev = 0; + result->next = 0; + result->busy_size = 0; + result->freed_size = 0; + + return result; + } + + xml_allocator* allocator; + + xml_memory_page* prev; + xml_memory_page* next; + + size_t busy_size; + size_t freed_size; + }; + + struct xml_memory_string_header + { + uint16_t page_offset; // offset from page->data + uint16_t full_size; // 0 if string occupies whole page + }; + + struct xml_allocator + { + xml_allocator(xml_memory_page* root): _root(root), _busy_size(root->busy_size) + { + } + + xml_memory_page* allocate_page(size_t data_size) + { + size_t size = sizeof(xml_memory_page) + data_size; + + // allocate block with some alignment, leaving memory for worst-case padding + void* memory = xml_memory::allocate(size + xml_memory_page_alignment); + if (!memory) return 0; + + // align to next page boundary (note: this guarantees at least 1 usable byte before the page) + char* page_memory = reinterpret_cast((reinterpret_cast(memory) + xml_memory_page_alignment) & ~(xml_memory_page_alignment - 1)); + + // prepare page structure + xml_memory_page* page = xml_memory_page::construct(page_memory); + assert(page); + + page->allocator = _root->allocator; + + // record the offset for freeing the memory block + assert(page_memory > memory && page_memory - static_cast(memory) <= 127); + page_memory[-1] = static_cast(page_memory - static_cast(memory)); + + return page; + } + + static void deallocate_page(xml_memory_page* page) + { + char* page_memory = reinterpret_cast(page); + + xml_memory::deallocate(page_memory - page_memory[-1]); + } + + void* allocate_memory_oob(size_t size, xml_memory_page*& out_page); + + void* allocate_memory(size_t size, xml_memory_page*& out_page) + { + if (_busy_size + size > xml_memory_page_size) return allocate_memory_oob(size, out_page); + + void* buf = reinterpret_cast(_root) + sizeof(xml_memory_page) + _busy_size; + + _busy_size += size; + + out_page = _root; + + return buf; + } + + void deallocate_memory(void* ptr, size_t size, xml_memory_page* page) + { + if (page == _root) page->busy_size = _busy_size; + + assert(ptr >= reinterpret_cast(page) + sizeof(xml_memory_page) && ptr < reinterpret_cast(page) + sizeof(xml_memory_page) + page->busy_size); + (void)!ptr; + + page->freed_size += size; + assert(page->freed_size <= page->busy_size); + + if (page->freed_size == page->busy_size) + { + if (page->next == 0) + { + assert(_root == page); + + // top page freed, just reset sizes + page->busy_size = page->freed_size = 0; + _busy_size = 0; + } + else + { + assert(_root != page); + assert(page->prev); + + // remove from the list + page->prev->next = page->next; + page->next->prev = page->prev; + + // deallocate + deallocate_page(page); + } + } + } + + char_t* allocate_string(size_t length) + { + PUGI__STATIC_ASSERT(xml_memory_page_size <= (1 << 16)); + + // allocate memory for string and header block + size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); + + // round size up to pointer alignment boundary + size_t full_size = (size + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1); + + xml_memory_page* page; + xml_memory_string_header* header = static_cast(allocate_memory(full_size, page)); + + if (!header) return 0; + + // setup header + ptrdiff_t page_offset = reinterpret_cast(header) - reinterpret_cast(page) - sizeof(xml_memory_page); + + assert(page_offset >= 0 && page_offset < (1 << 16)); + header->page_offset = static_cast(page_offset); + + // full_size == 0 for large strings that occupy the whole page + assert(full_size < (1 << 16) || (page->busy_size == full_size && page_offset == 0)); + header->full_size = static_cast(full_size < (1 << 16) ? full_size : 0); + + // round-trip through void* to avoid 'cast increases required alignment of target type' warning + // header is guaranteed a pointer-sized alignment, which should be enough for char_t + return static_cast(static_cast(header + 1)); + } + + void deallocate_string(char_t* string) + { + // this function casts pointers through void* to avoid 'cast increases required alignment of target type' warnings + // we're guaranteed the proper (pointer-sized) alignment on the input string if it was allocated via allocate_string + + // get header + xml_memory_string_header* header = static_cast(static_cast(string)) - 1; + assert(header); + + // deallocate + size_t page_offset = sizeof(xml_memory_page) + header->page_offset; + xml_memory_page* page = reinterpret_cast(static_cast(reinterpret_cast(header) - page_offset)); + + // if full_size == 0 then this string occupies the whole page + size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size; + + deallocate_memory(header, full_size, page); + } + + xml_memory_page* _root; + size_t _busy_size; + }; + + PUGI__FN_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page) + { + const size_t large_allocation_threshold = xml_memory_page_size / 4; + + xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size); + out_page = page; + + if (!page) return 0; + + if (size <= large_allocation_threshold) + { + _root->busy_size = _busy_size; + + // insert page at the end of linked list + page->prev = _root; + _root->next = page; + _root = page; + + _busy_size = size; + } + else + { + // insert page before the end of linked list, so that it is deleted as soon as possible + // the last page is not deleted even if it's empty (see deallocate_memory) + assert(_root->prev); + + page->prev = _root->prev; + page->next = _root; + + _root->prev->next = page; + _root->prev = page; + } + + // allocate inside page + page->busy_size = size; + + return reinterpret_cast(page) + sizeof(xml_memory_page); + } +PUGI__NS_END + +namespace pugi +{ + /// A 'name=value' XML attribute structure. + struct xml_attribute_struct + { + /// Default ctor + xml_attribute_struct(impl::xml_memory_page* page): header(reinterpret_cast(page)), name(0), value(0), prev_attribute_c(0), next_attribute(0) + { + } + + uintptr_t header; + + char_t* name; ///< Pointer to attribute name. + char_t* value; ///< Pointer to attribute value. + + xml_attribute_struct* prev_attribute_c; ///< Previous attribute (cyclic list) + xml_attribute_struct* next_attribute; ///< Next attribute + }; + + /// An XML document tree node. + struct xml_node_struct + { + /// Default ctor + /// \param type - node type + xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(reinterpret_cast(page) | (type - 1)), parent(0), name(0), value(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) + { + } + + uintptr_t header; + + xml_node_struct* parent; ///< Pointer to parent + + char_t* name; ///< Pointer to element name. + char_t* value; ///< Pointer to any associated string data. + + xml_node_struct* first_child; ///< First child + + xml_node_struct* prev_sibling_c; ///< Left brother (cyclic list) + xml_node_struct* next_sibling; ///< Right brother + + xml_attribute_struct* first_attribute; ///< First attribute + }; +} + +PUGI__NS_BEGIN + struct xml_extra_buffer + { + char_t* buffer; + xml_extra_buffer* next; + }; + + struct xml_document_struct: public xml_node_struct, public xml_allocator + { + xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0) + { + } + + const char_t* buffer; + + xml_extra_buffer* extra_buffers; + }; + + inline xml_allocator& get_allocator(const xml_node_struct* node) + { + assert(node); + + return *reinterpret_cast(node->header & xml_memory_page_pointer_mask)->allocator; + } + + template inline xml_document_struct& get_document(const Object* object) + { + assert(object); + + return *static_cast(reinterpret_cast(object->header & xml_memory_page_pointer_mask)->allocator); + } +PUGI__NS_END + +// Low-level DOM operations +PUGI__NS_BEGIN + inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) + { + xml_memory_page* page; + void* memory = alloc.allocate_memory(sizeof(xml_attribute_struct), page); + + return new (memory) xml_attribute_struct(page); + } + + inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type) + { + xml_memory_page* page; + void* memory = alloc.allocate_memory(sizeof(xml_node_struct), page); + + return new (memory) xml_node_struct(page, type); + } + + inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc) + { + uintptr_t header = a->header; + + if (header & impl::xml_memory_page_name_allocated_mask) alloc.deallocate_string(a->name); + if (header & impl::xml_memory_page_value_allocated_mask) alloc.deallocate_string(a->value); + + alloc.deallocate_memory(a, sizeof(xml_attribute_struct), reinterpret_cast(header & xml_memory_page_pointer_mask)); + } + + inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) + { + uintptr_t header = n->header; + + if (header & impl::xml_memory_page_name_allocated_mask) alloc.deallocate_string(n->name); + if (header & impl::xml_memory_page_value_allocated_mask) alloc.deallocate_string(n->value); + + for (xml_attribute_struct* attr = n->first_attribute; attr; ) + { + xml_attribute_struct* next = attr->next_attribute; + + destroy_attribute(attr, alloc); + + attr = next; + } + + for (xml_node_struct* child = n->first_child; child; ) + { + xml_node_struct* next = child->next_sibling; + + destroy_node(child, alloc); + + child = next; + } + + alloc.deallocate_memory(n, sizeof(xml_node_struct), reinterpret_cast(header & xml_memory_page_pointer_mask)); + } + + inline void append_node(xml_node_struct* child, xml_node_struct* node) + { + child->parent = node; + + xml_node_struct* head = node->first_child; + + if (head) + { + xml_node_struct* tail = head->prev_sibling_c; + + tail->next_sibling = child; + child->prev_sibling_c = tail; + head->prev_sibling_c = child; + } + else + { + node->first_child = child; + child->prev_sibling_c = child; + } + } + + inline void prepend_node(xml_node_struct* child, xml_node_struct* node) + { + child->parent = node; + + xml_node_struct* head = node->first_child; + + if (head) + { + child->prev_sibling_c = head->prev_sibling_c; + head->prev_sibling_c = child; + } + else + child->prev_sibling_c = child; + + child->next_sibling = head; + node->first_child = child; + } + + inline void insert_node_after(xml_node_struct* child, xml_node_struct* node) + { + xml_node_struct* parent = node->parent; + + child->parent = parent; + + if (node->next_sibling) + node->next_sibling->prev_sibling_c = child; + else + parent->first_child->prev_sibling_c = child; + + child->next_sibling = node->next_sibling; + child->prev_sibling_c = node; + + node->next_sibling = child; + } + + inline void insert_node_before(xml_node_struct* child, xml_node_struct* node) + { + xml_node_struct* parent = node->parent; + + child->parent = parent; + + if (node->prev_sibling_c->next_sibling) + node->prev_sibling_c->next_sibling = child; + else + parent->first_child = child; + + child->prev_sibling_c = node->prev_sibling_c; + child->next_sibling = node; + + node->prev_sibling_c = child; + } + + inline void remove_node(xml_node_struct* node) + { + xml_node_struct* parent = node->parent; + + if (node->next_sibling) + node->next_sibling->prev_sibling_c = node->prev_sibling_c; + else + parent->first_child->prev_sibling_c = node->prev_sibling_c; + + if (node->prev_sibling_c->next_sibling) + node->prev_sibling_c->next_sibling = node->next_sibling; + else + parent->first_child = node->next_sibling; + + node->parent = 0; + node->prev_sibling_c = 0; + node->next_sibling = 0; + } + + inline void append_attribute(xml_attribute_struct* attr, xml_node_struct* node) + { + xml_attribute_struct* head = node->first_attribute; + + if (head) + { + xml_attribute_struct* tail = head->prev_attribute_c; + + tail->next_attribute = attr; + attr->prev_attribute_c = tail; + head->prev_attribute_c = attr; + } + else + { + node->first_attribute = attr; + attr->prev_attribute_c = attr; + } + } + + inline void prepend_attribute(xml_attribute_struct* attr, xml_node_struct* node) + { + xml_attribute_struct* head = node->first_attribute; + + if (head) + { + attr->prev_attribute_c = head->prev_attribute_c; + head->prev_attribute_c = attr; + } + else + attr->prev_attribute_c = attr; + + attr->next_attribute = head; + node->first_attribute = attr; + } + + inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) + { + if (place->next_attribute) + place->next_attribute->prev_attribute_c = attr; + else + node->first_attribute->prev_attribute_c = attr; + + attr->next_attribute = place->next_attribute; + attr->prev_attribute_c = place; + place->next_attribute = attr; + } + + inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) + { + if (place->prev_attribute_c->next_attribute) + place->prev_attribute_c->next_attribute = attr; + else + node->first_attribute = attr; + + attr->prev_attribute_c = place->prev_attribute_c; + attr->next_attribute = place; + place->prev_attribute_c = attr; + } + + inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node) + { + if (attr->next_attribute) + attr->next_attribute->prev_attribute_c = attr->prev_attribute_c; + else + node->first_attribute->prev_attribute_c = attr->prev_attribute_c; + + if (attr->prev_attribute_c->next_attribute) + attr->prev_attribute_c->next_attribute = attr->next_attribute; + else + node->first_attribute = attr->next_attribute; + + attr->prev_attribute_c = 0; + attr->next_attribute = 0; + } + + PUGI__FN_NO_INLINE xml_node_struct* append_new_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) + { + xml_node_struct* child = allocate_node(alloc, type); + if (!child) return 0; + + append_node(child, node); + + return child; + } + + PUGI__FN_NO_INLINE xml_attribute_struct* append_new_attribute(xml_node_struct* node, xml_allocator& alloc) + { + xml_attribute_struct* attr = allocate_attribute(alloc); + if (!attr) return 0; + + append_attribute(attr, node); + + return attr; + } +PUGI__NS_END + +// Helper classes for code generation +PUGI__NS_BEGIN + struct opt_false + { + enum { value = 0 }; + }; + + struct opt_true + { + enum { value = 1 }; + }; +PUGI__NS_END + +// Unicode utilities +PUGI__NS_BEGIN + inline uint16_t endian_swap(uint16_t value) + { + return static_cast(((value & 0xff) << 8) | (value >> 8)); + } + + inline uint32_t endian_swap(uint32_t value) + { + return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24); + } + + struct utf8_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t ch) + { + // U+0000..U+007F + if (ch < 0x80) return result + 1; + // U+0080..U+07FF + else if (ch < 0x800) return result + 2; + // U+0800..U+FFFF + else return result + 3; + } + + static value_type high(value_type result, uint32_t) + { + // U+10000..U+10FFFF + return result + 4; + } + }; + + struct utf8_writer + { + typedef uint8_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + // U+0000..U+007F + if (ch < 0x80) + { + *result = static_cast(ch); + return result + 1; + } + // U+0080..U+07FF + else if (ch < 0x800) + { + result[0] = static_cast(0xC0 | (ch >> 6)); + result[1] = static_cast(0x80 | (ch & 0x3F)); + return result + 2; + } + // U+0800..U+FFFF + else + { + result[0] = static_cast(0xE0 | (ch >> 12)); + result[1] = static_cast(0x80 | ((ch >> 6) & 0x3F)); + result[2] = static_cast(0x80 | (ch & 0x3F)); + return result + 3; + } + } + + static value_type high(value_type result, uint32_t ch) + { + // U+10000..U+10FFFF + result[0] = static_cast(0xF0 | (ch >> 18)); + result[1] = static_cast(0x80 | ((ch >> 12) & 0x3F)); + result[2] = static_cast(0x80 | ((ch >> 6) & 0x3F)); + result[3] = static_cast(0x80 | (ch & 0x3F)); + return result + 4; + } + + static value_type any(value_type result, uint32_t ch) + { + return (ch < 0x10000) ? low(result, ch) : high(result, ch); + } + }; + + struct utf16_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t) + { + return result + 1; + } + + static value_type high(value_type result, uint32_t) + { + return result + 2; + } + }; + + struct utf16_writer + { + typedef uint16_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + *result = static_cast(ch); + + return result + 1; + } + + static value_type high(value_type result, uint32_t ch) + { + uint32_t msh = static_cast(ch - 0x10000) >> 10; + uint32_t lsh = static_cast(ch - 0x10000) & 0x3ff; + + result[0] = static_cast(0xD800 + msh); + result[1] = static_cast(0xDC00 + lsh); + + return result + 2; + } + + static value_type any(value_type result, uint32_t ch) + { + return (ch < 0x10000) ? low(result, ch) : high(result, ch); + } + }; + + struct utf32_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t) + { + return result + 1; + } + + static value_type high(value_type result, uint32_t) + { + return result + 1; + } + }; + + struct utf32_writer + { + typedef uint32_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + + static value_type high(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + + static value_type any(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + }; + + struct latin1_writer + { + typedef uint8_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + *result = static_cast(ch > 255 ? '?' : ch); + + return result + 1; + } + + static value_type high(value_type result, uint32_t ch) + { + (void)ch; + + *result = '?'; + + return result + 1; + } + }; + + template struct wchar_selector; + + template <> struct wchar_selector<2> + { + typedef uint16_t type; + typedef utf16_counter counter; + typedef utf16_writer writer; + }; + + template <> struct wchar_selector<4> + { + typedef uint32_t type; + typedef utf32_counter counter; + typedef utf32_writer writer; + }; + + typedef wchar_selector::counter wchar_counter; + typedef wchar_selector::writer wchar_writer; + + template struct utf_decoder + { + static inline typename Traits::value_type decode_utf8_block(const uint8_t* data, size_t size, typename Traits::value_type result) + { + const uint8_t utf8_byte_mask = 0x3f; + + while (size) + { + uint8_t lead = *data; + + // 0xxxxxxx -> U+0000..U+007F + if (lead < 0x80) + { + result = Traits::low(result, lead); + data += 1; + size -= 1; + + // process aligned single-byte (ascii) blocks + if ((reinterpret_cast(data) & 3) == 0) + { + // round-trip through void* to silence 'cast increases required alignment of target type' warnings + while (size >= 4 && (*static_cast(static_cast(data)) & 0x80808080) == 0) + { + result = Traits::low(result, data[0]); + result = Traits::low(result, data[1]); + result = Traits::low(result, data[2]); + result = Traits::low(result, data[3]); + data += 4; + size -= 4; + } + } + } + // 110xxxxx -> U+0080..U+07FF + else if (static_cast(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80) + { + result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask)); + data += 2; + size -= 2; + } + // 1110xxxx -> U+0800-U+FFFF + else if (static_cast(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80) + { + result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask)); + data += 3; + size -= 3; + } + // 11110xxx -> U+10000..U+10FFFF + else if (static_cast(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80) + { + result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask)); + data += 4; + size -= 4; + } + // 10xxxxxx or 11111xxx -> invalid + else + { + data += 1; + size -= 1; + } + } + + return result; + } + + static inline typename Traits::value_type decode_utf16_block(const uint16_t* data, size_t size, typename Traits::value_type result) + { + const uint16_t* end = data + size; + + while (data < end) + { + unsigned int lead = opt_swap::value ? endian_swap(*data) : *data; + + // U+0000..U+D7FF + if (lead < 0xD800) + { + result = Traits::low(result, lead); + data += 1; + } + // U+E000..U+FFFF + else if (static_cast(lead - 0xE000) < 0x2000) + { + result = Traits::low(result, lead); + data += 1; + } + // surrogate pair lead + else if (static_cast(lead - 0xD800) < 0x400 && data + 1 < end) + { + uint16_t next = opt_swap::value ? endian_swap(data[1]) : data[1]; + + if (static_cast(next - 0xDC00) < 0x400) + { + result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff)); + data += 2; + } + else + { + data += 1; + } + } + else + { + data += 1; + } + } + + return result; + } + + static inline typename Traits::value_type decode_utf32_block(const uint32_t* data, size_t size, typename Traits::value_type result) + { + const uint32_t* end = data + size; + + while (data < end) + { + uint32_t lead = opt_swap::value ? endian_swap(*data) : *data; + + // U+0000..U+FFFF + if (lead < 0x10000) + { + result = Traits::low(result, lead); + data += 1; + } + // U+10000..U+10FFFF + else + { + result = Traits::high(result, lead); + data += 1; + } + } + + return result; + } + + static inline typename Traits::value_type decode_latin1_block(const uint8_t* data, size_t size, typename Traits::value_type result) + { + for (size_t i = 0; i < size; ++i) + { + result = Traits::low(result, data[i]); + } + + return result; + } + + static inline typename Traits::value_type decode_wchar_block_impl(const uint16_t* data, size_t size, typename Traits::value_type result) + { + return decode_utf16_block(data, size, result); + } + + static inline typename Traits::value_type decode_wchar_block_impl(const uint32_t* data, size_t size, typename Traits::value_type result) + { + return decode_utf32_block(data, size, result); + } + + static inline typename Traits::value_type decode_wchar_block(const wchar_t* data, size_t size, typename Traits::value_type result) + { + return decode_wchar_block_impl(reinterpret_cast::type*>(data), size, result); + } + }; + + template PUGI__FN void convert_utf_endian_swap(T* result, const T* data, size_t length) + { + for (size_t i = 0; i < length; ++i) result[i] = endian_swap(data[i]); + } + +#ifdef PUGIXML_WCHAR_MODE + PUGI__FN void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length) + { + for (size_t i = 0; i < length; ++i) result[i] = static_cast(endian_swap(static_cast::type>(data[i]))); + } +#endif +PUGI__NS_END + +PUGI__NS_BEGIN + enum chartype_t + { + ct_parse_pcdata = 1, // \0, &, \r, < + ct_parse_attr = 2, // \0, &, \r, ', " + ct_parse_attr_ws = 4, // \0, &, \r, ', ", \n, tab + ct_space = 8, // \r, \n, space, tab + ct_parse_cdata = 16, // \0, ], >, \r + ct_parse_comment = 32, // \0, -, >, \r + ct_symbol = 64, // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, . + ct_start_symbol = 128 // Any symbol > 127, a-z, A-Z, _, : + }; + + static const unsigned char chartype_table[256] = + { + 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47 + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63 + 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79 + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95 + 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111 + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127 + + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+ + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192 + }; + + enum chartypex_t + { + ctx_special_pcdata = 1, // Any symbol >= 0 and < 32 (except \t, \r, \n), &, <, > + ctx_special_attr = 2, // Any symbol >= 0 and < 32 (except \t), &, <, >, " + ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _ + ctx_digit = 8, // 0-9 + ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, . + }; + + static const unsigned char chartypex_table[256] = + { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3, // 0-15 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31 + 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 3, 0, // 48-63 + + 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 64-79 + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20, // 80-95 + 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 96-111 + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, // 112-127 + + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 128+ + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 + }; + +#ifdef PUGIXML_WCHAR_MODE + #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast(c) < 128 ? table[static_cast(c)] : table[128]) & (ct)) +#else + #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast(c)] & (ct)) +#endif + + #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table) + #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table) + + PUGI__FN bool is_little_endian() + { + unsigned int ui = 1; + + return *reinterpret_cast(&ui) == 1; + } + + PUGI__FN xml_encoding get_wchar_encoding() + { + PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); + + if (sizeof(wchar_t) == 2) + return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + else + return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + } + + PUGI__FN xml_encoding guess_buffer_encoding(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) + { + // look for BOM in first few bytes + if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be; + if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le; + if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be; + if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le; + if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf) return encoding_utf8; + + // look for <, (contents); + + PUGI__DMC_VOLATILE uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3]; + + return guess_buffer_encoding(d0, d1, d2, d3); + } + + PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + { + size_t length = size / sizeof(char_t); + + if (is_mutable) + { + out_buffer = static_cast(const_cast(contents)); + out_length = length; + } + else + { + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + if (contents) + memcpy(buffer, contents, length * sizeof(char_t)); + else + assert(length == 0); + + buffer[length] = 0; + + out_buffer = buffer; + out_length = length + 1; + } + + return true; + } + +#ifdef PUGIXML_WCHAR_MODE + PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re) + { + return (le == encoding_utf16_be && re == encoding_utf16_le) || (le == encoding_utf16_le && re == encoding_utf16_be) || + (le == encoding_utf32_be && re == encoding_utf32_le) || (le == encoding_utf32_le && re == encoding_utf32_be); + } + + PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + { + const char_t* data = static_cast(contents); + size_t length = size / sizeof(char_t); + + if (is_mutable) + { + char_t* buffer = const_cast(data); + + convert_wchar_endian_swap(buffer, data, length); + + out_buffer = buffer; + out_length = length; + } + else + { + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + convert_wchar_endian_swap(buffer, data, length); + buffer[length] = 0; + + out_buffer = buffer; + out_length = length + 1; + } + + return true; + } + + PUGI__FN bool convert_buffer_utf8(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size) + { + const uint8_t* data = static_cast(contents); + size_t data_length = size; + + // first pass: get length in wchar_t units + size_t length = utf_decoder::decode_utf8_block(data, data_length, 0); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert utf8 input to wchar_t + wchar_writer::value_type obegin = reinterpret_cast(buffer); + wchar_writer::value_type oend = utf_decoder::decode_utf8_block(data, data_length, obegin); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + template PUGI__FN bool convert_buffer_utf16(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) + { + const uint16_t* data = static_cast(contents); + size_t data_length = size / sizeof(uint16_t); + + // first pass: get length in wchar_t units + size_t length = utf_decoder::decode_utf16_block(data, data_length, 0); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert utf16 input to wchar_t + wchar_writer::value_type obegin = reinterpret_cast(buffer); + wchar_writer::value_type oend = utf_decoder::decode_utf16_block(data, data_length, obegin); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + template PUGI__FN bool convert_buffer_utf32(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) + { + const uint32_t* data = static_cast(contents); + size_t data_length = size / sizeof(uint32_t); + + // first pass: get length in wchar_t units + size_t length = utf_decoder::decode_utf32_block(data, data_length, 0); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert utf32 input to wchar_t + wchar_writer::value_type obegin = reinterpret_cast(buffer); + wchar_writer::value_type oend = utf_decoder::decode_utf32_block(data, data_length, obegin); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size) + { + const uint8_t* data = static_cast(contents); + size_t data_length = size; + + // get length in wchar_t units + size_t length = data_length; + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // convert latin1 input to wchar_t + wchar_writer::value_type obegin = reinterpret_cast(buffer); + wchar_writer::value_type oend = utf_decoder::decode_latin1_block(data, data_length, obegin); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) + { + // get native encoding + xml_encoding wchar_encoding = get_wchar_encoding(); + + // fast path: no conversion required + if (encoding == wchar_encoding) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); + + // only endian-swapping is required + if (need_endian_swap_utf(encoding, wchar_encoding)) return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable); + + // source encoding is utf8 + if (encoding == encoding_utf8) return convert_buffer_utf8(out_buffer, out_length, contents, size); + + // source encoding is utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + return (native_encoding == encoding) ? + convert_buffer_utf16(out_buffer, out_length, contents, size, opt_false()) : + convert_buffer_utf16(out_buffer, out_length, contents, size, opt_true()); + } + + // source encoding is utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + return (native_encoding == encoding) ? + convert_buffer_utf32(out_buffer, out_length, contents, size, opt_false()) : + convert_buffer_utf32(out_buffer, out_length, contents, size, opt_true()); + } + + // source encoding is latin1 + if (encoding == encoding_latin1) return convert_buffer_latin1(out_buffer, out_length, contents, size); + + assert(!"Invalid encoding"); + return false; + } +#else + template PUGI__FN bool convert_buffer_utf16(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) + { + const uint16_t* data = static_cast(contents); + size_t data_length = size / sizeof(uint16_t); + + // first pass: get length in utf8 units + size_t length = utf_decoder::decode_utf16_block(data, data_length, 0); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert utf16 input to utf8 + uint8_t* obegin = reinterpret_cast(buffer); + uint8_t* oend = utf_decoder::decode_utf16_block(data, data_length, obegin); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + template PUGI__FN bool convert_buffer_utf32(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) + { + const uint32_t* data = static_cast(contents); + size_t data_length = size / sizeof(uint32_t); + + // first pass: get length in utf8 units + size_t length = utf_decoder::decode_utf32_block(data, data_length, 0); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert utf32 input to utf8 + uint8_t* obegin = reinterpret_cast(buffer); + uint8_t* oend = utf_decoder::decode_utf32_block(data, data_length, obegin); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + PUGI__FN size_t get_latin1_7bit_prefix_length(const uint8_t* data, size_t size) + { + for (size_t i = 0; i < size; ++i) + if (data[i] > 127) + return i; + + return size; + } + + PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + { + const uint8_t* data = static_cast(contents); + size_t data_length = size; + + // get size of prefix that does not need utf8 conversion + size_t prefix_length = get_latin1_7bit_prefix_length(data, data_length); + assert(prefix_length <= data_length); + + const uint8_t* postfix = data + prefix_length; + size_t postfix_length = data_length - prefix_length; + + // if no conversion is needed, just return the original buffer + if (postfix_length == 0) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); + + // first pass: get length in utf8 units + size_t length = prefix_length + utf_decoder::decode_latin1_block(postfix, postfix_length, 0); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert latin1 input to utf8 + memcpy(buffer, data, prefix_length); + + uint8_t* obegin = reinterpret_cast(buffer); + uint8_t* oend = utf_decoder::decode_latin1_block(postfix, postfix_length, obegin + prefix_length); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) + { + // fast path: no conversion required + if (encoding == encoding_utf8) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); + + // source encoding is utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + return (native_encoding == encoding) ? + convert_buffer_utf16(out_buffer, out_length, contents, size, opt_false()) : + convert_buffer_utf16(out_buffer, out_length, contents, size, opt_true()); + } + + // source encoding is utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + return (native_encoding == encoding) ? + convert_buffer_utf32(out_buffer, out_length, contents, size, opt_false()) : + convert_buffer_utf32(out_buffer, out_length, contents, size, opt_true()); + } + + // source encoding is latin1 + if (encoding == encoding_latin1) return convert_buffer_latin1(out_buffer, out_length, contents, size, is_mutable); + + assert(!"Invalid encoding"); + return false; + } +#endif + + PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length) + { + // get length in utf8 characters + return utf_decoder::decode_wchar_block(str, length, 0); + } + + PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) + { + // convert to utf8 + uint8_t* begin = reinterpret_cast(buffer); + uint8_t* end = utf_decoder::decode_wchar_block(str, length, begin); + + assert(begin + size == end); + (void)!end; + + // zero-terminate + buffer[size] = 0; + } + +#ifndef PUGIXML_NO_STL + PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length) + { + // first pass: get length in utf8 characters + size_t size = as_utf8_begin(str, length); + + // allocate resulting string + std::string result; + result.resize(size); + + // second pass: convert to utf8 + if (size > 0) as_utf8_end(&result[0], size, str, length); + + return result; + } + + PUGI__FN std::basic_string as_wide_impl(const char* str, size_t size) + { + const uint8_t* data = reinterpret_cast(str); + + // first pass: get length in wchar_t units + size_t length = utf_decoder::decode_utf8_block(data, size, 0); + + // allocate resulting string + std::basic_string result; + result.resize(length); + + // second pass: convert to wchar_t + if (length > 0) + { + wchar_writer::value_type begin = reinterpret_cast(&result[0]); + wchar_writer::value_type end = utf_decoder::decode_utf8_block(data, size, begin); + + assert(begin + length == end); + (void)!end; + } + + return result; + } +#endif + + inline bool strcpy_insitu_allow(size_t length, uintptr_t header, uintptr_t header_mask, char_t* target) + { + // never reuse shared memory + if (header & xml_memory_page_contents_shared_mask) return false; + + size_t target_length = strlength(target); + + // always reuse document buffer memory if possible + if ((header & header_mask) == 0) return target_length >= length; + + // reuse heap memory if waste is not too great + const size_t reuse_threshold = 32; + + return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2); + } + + PUGI__FN bool strcpy_insitu(char_t*& dest, uintptr_t& header, uintptr_t header_mask, const char_t* source) + { + assert(header); + + size_t source_length = strlength(source); + + if (source_length == 0) + { + // empty string and null pointer are equivalent, so just deallocate old memory + xml_allocator* alloc = reinterpret_cast(header & xml_memory_page_pointer_mask)->allocator; + + if (header & header_mask) alloc->deallocate_string(dest); + + // mark the string as not allocated + dest = 0; + header &= ~header_mask; + + return true; + } + else if (dest && strcpy_insitu_allow(source_length, header, header_mask, dest)) + { + // we can reuse old buffer, so just copy the new data (including zero terminator) + memcpy(dest, source, (source_length + 1) * sizeof(char_t)); + + return true; + } + else + { + xml_allocator* alloc = reinterpret_cast(header & xml_memory_page_pointer_mask)->allocator; + + // allocate new buffer + char_t* buf = alloc->allocate_string(source_length + 1); + if (!buf) return false; + + // copy the string (including zero terminator) + memcpy(buf, source, (source_length + 1) * sizeof(char_t)); + + // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures) + if (header & header_mask) alloc->deallocate_string(dest); + + // the string is now allocated, so set the flag + dest = buf; + header |= header_mask; + + return true; + } + } + + struct gap + { + char_t* end; + size_t size; + + gap(): end(0), size(0) + { + } + + // Push new gap, move s count bytes further (skipping the gap). + // Collapse previous gap. + void push(char_t*& s, size_t count) + { + if (end) // there was a gap already; collapse it + { + // Move [old_gap_end, new_gap_start) to [old_gap_start, ...) + assert(s >= end); + memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); + } + + s += count; // end of current gap + + // "merge" two gaps + end = s; + size += count; + } + + // Collapse all gaps, return past-the-end pointer + char_t* flush(char_t* s) + { + if (end) + { + // Move [old_gap_end, current_pos) to [old_gap_start, ...) + assert(s >= end); + memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); + + return s - size; + } + else return s; + } + }; + + PUGI__FN char_t* strconv_escape(char_t* s, gap& g) + { + char_t* stre = s + 1; + + switch (*stre) + { + case '#': // &#... + { + unsigned int ucsc = 0; + + if (stre[1] == 'x') // &#x... (hex code) + { + stre += 2; + + char_t ch = *stre; + + if (ch == ';') return stre; + + for (;;) + { + if (static_cast(ch - '0') <= 9) + ucsc = 16 * ucsc + (ch - '0'); + else if (static_cast((ch | ' ') - 'a') <= 5) + ucsc = 16 * ucsc + ((ch | ' ') - 'a' + 10); + else if (ch == ';') + break; + else // cancel + return stre; + + ch = *++stre; + } + + ++stre; + } + else // &#... (dec code) + { + char_t ch = *++stre; + + if (ch == ';') return stre; + + for (;;) + { + if (static_cast(static_cast(ch) - '0') <= 9) + ucsc = 10 * ucsc + (ch - '0'); + else if (ch == ';') + break; + else // cancel + return stre; + + ch = *++stre; + } + + ++stre; + } + + #ifdef PUGIXML_WCHAR_MODE + s = reinterpret_cast(wchar_writer::any(reinterpret_cast(s), ucsc)); + #else + s = reinterpret_cast(utf8_writer::any(reinterpret_cast(s), ucsc)); + #endif + + g.push(s, stre - s); + return stre; + } + + case 'a': // &a + { + ++stre; + + if (*stre == 'm') // &am + { + if (*++stre == 'p' && *++stre == ';') // & + { + *s++ = '&'; + ++stre; + + g.push(s, stre - s); + return stre; + } + } + else if (*stre == 'p') // &ap + { + if (*++stre == 'o' && *++stre == 's' && *++stre == ';') // ' + { + *s++ = '\''; + ++stre; + + g.push(s, stre - s); + return stre; + } + } + break; + } + + case 'g': // &g + { + if (*++stre == 't' && *++stre == ';') // > + { + *s++ = '>'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + + case 'l': // &l + { + if (*++stre == 't' && *++stre == ';') // < + { + *s++ = '<'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + + case 'q': // &q + { + if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // " + { + *s++ = '"'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + + default: + break; + } + + return stre; + } + + // Parser utilities + #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) + #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; } + #define PUGI__OPTSET(OPT) ( optmsk & (OPT) ) + #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); } + #define PUGI__POPNODE() { cursor = cursor->parent; } + #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; } + #define PUGI__SCANWHILE(X) { while (X) ++s; } + #define PUGI__SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI__UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI__UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI__UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI__UNLIKELY(!(X))) { s += 3; break; } s += 4; } } + #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; } + #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(0) + #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); } + + PUGI__FN char_t* strconv_comment(char_t* s, char_t endch) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment)); + + if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')) // comment ends here + { + *g.flush(s) = 0; + + return s + (s[2] == '>' ? 3 : 2); + } + else if (*s == 0) + { + return 0; + } + else ++s; + } + } + + PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata)); + + if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')) // CDATA ends here + { + *g.flush(s) = 0; + + return s + 1; + } + else if (*s == 0) + { + return 0; + } + else ++s; + } + } + + typedef char_t* (*strconv_pcdata_t)(char_t*); + + template struct strconv_pcdata_impl + { + static char_t* parse(char_t* s) + { + gap g; + + char_t* begin = s; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_pcdata)); + + if (*s == '<') // PCDATA ends here + { + char_t* end = g.flush(s); + + if (opt_trim::value) + while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) + --end; + + *end = 0; + + return s + 1; + } + else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (*s == 0) + { + char_t* end = g.flush(s); + + if (opt_trim::value) + while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) + --end; + + *end = 0; + + return s; + } + else ++s; + } + } + }; + + PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) + { + PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800); + + switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (eol escapes trim) + { + case 0: return strconv_pcdata_impl::parse; + case 1: return strconv_pcdata_impl::parse; + case 2: return strconv_pcdata_impl::parse; + case 3: return strconv_pcdata_impl::parse; + case 4: return strconv_pcdata_impl::parse; + case 5: return strconv_pcdata_impl::parse; + case 6: return strconv_pcdata_impl::parse; + case 7: return strconv_pcdata_impl::parse; + default: assert(false); return 0; // should not get here + } + } + + typedef char_t* (*strconv_attribute_t)(char_t*, char_t); + + template struct strconv_attribute_impl + { + static char_t* parse_wnorm(char_t* s, char_t end_quote) + { + gap g; + + // trim leading whitespaces + if (PUGI__IS_CHARTYPE(*s, ct_space)) + { + char_t* str = s; + + do ++str; + while (PUGI__IS_CHARTYPE(*str, ct_space)); + + g.push(s, str - s); + } + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space)); + + if (*s == end_quote) + { + char_t* str = g.flush(s); + + do *str-- = 0; + while (PUGI__IS_CHARTYPE(*str, ct_space)); + + return s + 1; + } + else if (PUGI__IS_CHARTYPE(*s, ct_space)) + { + *s++ = ' '; + + if (PUGI__IS_CHARTYPE(*s, ct_space)) + { + char_t* str = s + 1; + while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str; + + g.push(s, str - s); + } + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_wconv(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws)); + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (PUGI__IS_CHARTYPE(*s, ct_space)) + { + if (*s == '\r') + { + *s++ = ' '; + + if (*s == '\n') g.push(s, 1); + } + else *s++ = ' '; + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_eol(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (*s == '\r') + { + *s++ = '\n'; + + if (*s == '\n') g.push(s, 1); + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_simple(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + }; + + PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask) + { + PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); + + switch ((optmask >> 4) & 15) // get bitmask for flags (wconv wnorm eol escapes) + { + case 0: return strconv_attribute_impl::parse_simple; + case 1: return strconv_attribute_impl::parse_simple; + case 2: return strconv_attribute_impl::parse_eol; + case 3: return strconv_attribute_impl::parse_eol; + case 4: return strconv_attribute_impl::parse_wconv; + case 5: return strconv_attribute_impl::parse_wconv; + case 6: return strconv_attribute_impl::parse_wconv; + case 7: return strconv_attribute_impl::parse_wconv; + case 8: return strconv_attribute_impl::parse_wnorm; + case 9: return strconv_attribute_impl::parse_wnorm; + case 10: return strconv_attribute_impl::parse_wnorm; + case 11: return strconv_attribute_impl::parse_wnorm; + case 12: return strconv_attribute_impl::parse_wnorm; + case 13: return strconv_attribute_impl::parse_wnorm; + case 14: return strconv_attribute_impl::parse_wnorm; + case 15: return strconv_attribute_impl::parse_wnorm; + default: assert(false); return 0; // should not get here + } + } + + inline xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset = 0) + { + xml_parse_result result; + result.status = status; + result.offset = offset; + + return result; + } + + struct xml_parser + { + xml_allocator alloc; + char_t* error_offset; + xml_parse_status error_status; + + xml_parser(const xml_allocator& alloc_): alloc(alloc_), error_offset(0), error_status(status_ok) + { + } + + // DOCTYPE consists of nested sections of the following possible types: + // , , "...", '...' + // + // + // First group can not contain nested groups + // Second group can contain nested groups of the same type + // Third group can contain all other groups + char_t* parse_doctype_primitive(char_t* s) + { + if (*s == '"' || *s == '\'') + { + // quoted string + char_t ch = *s++; + PUGI__SCANFOR(*s == ch); + if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + + s++; + } + else if (s[0] == '<' && s[1] == '?') + { + // + s += 2; + PUGI__SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype + if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + + s += 2; + } + else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-') + { + s += 4; + PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype + if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + + s += 4; + } + else PUGI__THROW_ERROR(status_bad_doctype, s); + + return s; + } + + char_t* parse_doctype_ignore(char_t* s) + { + size_t depth = 0; + + assert(s[0] == '<' && s[1] == '!' && s[2] == '['); + s += 3; + + while (*s) + { + if (s[0] == '<' && s[1] == '!' && s[2] == '[') + { + // nested ignore section + s += 3; + depth++; + } + else if (s[0] == ']' && s[1] == ']' && s[2] == '>') + { + // ignore section end + s += 3; + + if (depth == 0) + return s; + + depth--; + } + else s++; + } + + PUGI__THROW_ERROR(status_bad_doctype, s); + } + + char_t* parse_doctype_group(char_t* s, char_t endch) + { + size_t depth = 0; + + assert((s[0] == '<' || s[0] == 0) && s[1] == '!'); + s += 2; + + while (*s) + { + if (s[0] == '<' && s[1] == '!' && s[2] != '-') + { + if (s[2] == '[') + { + // ignore + s = parse_doctype_ignore(s); + if (!s) return s; + } + else + { + // some control group + s += 2; + depth++; + } + } + else if (s[0] == '<' || s[0] == '"' || s[0] == '\'') + { + // unknown tag (forbidden), or some primitive group + s = parse_doctype_primitive(s); + if (!s) return s; + } + else if (*s == '>') + { + if (depth == 0) + return s; + + depth--; + s++; + } + else s++; + } + + if (depth != 0 || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s); + + return s; + } + + char_t* parse_exclamation(char_t* s, xml_node_struct* cursor, unsigned int optmsk, char_t endch) + { + // parse node contents, starting with exclamation mark + ++s; + + if (*s == '-') // 'value = s; // Save the offset. + } + + if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments)) + { + s = strconv_comment(s, endch); + + if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value); + } + else + { + // Scan for terminating '-->'. + PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')); + PUGI__CHECK_ERROR(status_bad_comment, s); + + if (PUGI__OPTSET(parse_comments)) + *s = 0; // Zero-terminate this segment at the first terminating '-'. + + s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'. + } + } + else PUGI__THROW_ERROR(status_bad_comment, s); + } + else if (*s == '[') + { + // 'value = s; // Save the offset. + + if (PUGI__OPTSET(parse_eol)) + { + s = strconv_cdata(s, endch); + + if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value); + } + else + { + // Scan for terminating ']]>'. + PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); + PUGI__CHECK_ERROR(status_bad_cdata, s); + + *s++ = 0; // Zero-terminate this segment. + } + } + else // Flagged for discard, but we still have to scan for the terminator. + { + // Scan for terminating ']]>'. + PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); + PUGI__CHECK_ERROR(status_bad_cdata, s); + + ++s; + } + + s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'. + } + else PUGI__THROW_ERROR(status_bad_cdata, s); + } + else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && PUGI__ENDSWITH(s[6], 'E')) + { + s -= 2; + + if (cursor->parent) PUGI__THROW_ERROR(status_bad_doctype, s); + + char_t* mark = s + 9; + + s = parse_doctype_group(s, endch); + if (!s) return s; + + assert((*s == 0 && endch == '>') || *s == '>'); + if (*s) *s++ = 0; + + if (PUGI__OPTSET(parse_doctype)) + { + while (PUGI__IS_CHARTYPE(*mark, ct_space)) ++mark; + + PUGI__PUSHNODE(node_doctype); + + cursor->value = mark; + } + } + else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s); + else if (*s == 0 && endch == '[') PUGI__THROW_ERROR(status_bad_cdata, s); + else PUGI__THROW_ERROR(status_unrecognized_tag, s); + + return s; + } + + char_t* parse_question(char_t* s, xml_node_struct*& ref_cursor, unsigned int optmsk, char_t endch) + { + // load into registers + xml_node_struct* cursor = ref_cursor; + char_t ch = 0; + + // parse node contents, starting with question mark + ++s; + + // read PI target + char_t* target = s; + + if (!PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_pi, s); + + PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol)); + PUGI__CHECK_ERROR(status_bad_pi, s); + + // determine node type; stricmp / strcasecmp is not portable + bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s; + + if (declaration ? PUGI__OPTSET(parse_declaration) : PUGI__OPTSET(parse_pi)) + { + if (declaration) + { + // disallow non top-level declarations + if (cursor->parent) PUGI__THROW_ERROR(status_bad_pi, s); + + PUGI__PUSHNODE(node_declaration); + } + else + { + PUGI__PUSHNODE(node_pi); + } + + cursor->name = target; + + PUGI__ENDSEG(); + + // parse value/attributes + if (ch == '?') + { + // empty node + if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_pi, s); + s += (*s == '>'); + + PUGI__POPNODE(); + } + else if (PUGI__IS_CHARTYPE(ch, ct_space)) + { + PUGI__SKIPWS(); + + // scan for tag end + char_t* value = s; + + PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); + PUGI__CHECK_ERROR(status_bad_pi, s); + + if (declaration) + { + // replace ending ? with / so that 'element' terminates properly + *s = '/'; + + // we exit from this function with cursor at node_declaration, which is a signal to parse() to go to LOC_ATTRIBUTES + s = value; + } + else + { + // store value and step over > + cursor->value = value; + PUGI__POPNODE(); + + PUGI__ENDSEG(); + + s += (*s == '>'); + } + } + else PUGI__THROW_ERROR(status_bad_pi, s); + } + else + { + // scan for tag end + PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); + PUGI__CHECK_ERROR(status_bad_pi, s); + + s += (s[1] == '>' ? 2 : 1); + } + + // store from registers + ref_cursor = cursor; + + return s; + } + + char_t* parse_tree(char_t* s, xml_node_struct* root, unsigned int optmsk, char_t endch) + { + strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk); + strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk); + + char_t ch = 0; + xml_node_struct* cursor = root; + char_t* mark = s; + + while (*s != 0) + { + if (*s == '<') + { + ++s; + + LOC_TAG: + if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // '<#...' + { + PUGI__PUSHNODE(node_element); // Append a new node to the tree. + + cursor->name = s; + + PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. + PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. + + if (ch == '>') + { + // end of tag + } + else if (PUGI__IS_CHARTYPE(ch, ct_space)) + { + LOC_ATTRIBUTES: + while (true) + { + PUGI__SKIPWS(); // Eat any whitespace. + + if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #... + { + xml_attribute_struct* a = append_new_attribute(cursor, alloc); // Make space for this attribute. + if (!a) PUGI__THROW_ERROR(status_out_of_memory, s); + + a->name = s; // Save the offset. + + PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. + PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. + + if (PUGI__IS_CHARTYPE(ch, ct_space)) + { + PUGI__SKIPWS(); // Eat any whitespace. + + ch = *s; + ++s; + } + + if (ch == '=') // '<... #=...' + { + PUGI__SKIPWS(); // Eat any whitespace. + + if (*s == '"' || *s == '\'') // '<... #="...' + { + ch = *s; // Save quote char to avoid breaking on "''" -or- '""'. + ++s; // Step over the quote. + a->value = s; // Save the offset. + + s = strconv_attribute(s, ch); + + if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value); + + // After this line the loop continues from the start; + // Whitespaces, / and > are ok, symbols and EOF are wrong, + // everything else will be detected + if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_attribute, s); + } + else PUGI__THROW_ERROR(status_bad_attribute, s); + } + else PUGI__THROW_ERROR(status_bad_attribute, s); + } + else if (*s == '/') + { + ++s; + + if (*s == '>') + { + PUGI__POPNODE(); + s++; + break; + } + else if (*s == 0 && endch == '>') + { + PUGI__POPNODE(); + break; + } + else PUGI__THROW_ERROR(status_bad_start_element, s); + } + else if (*s == '>') + { + ++s; + + break; + } + else if (*s == 0 && endch == '>') + { + break; + } + else PUGI__THROW_ERROR(status_bad_start_element, s); + } + + // !!! + } + else if (ch == '/') // '<#.../' + { + if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_start_element, s); + + PUGI__POPNODE(); // Pop. + + s += (*s == '>'); + } + else if (ch == 0) + { + // we stepped over null terminator, backtrack & handle closing tag + --s; + + if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s); + } + else PUGI__THROW_ERROR(status_bad_start_element, s); + } + else if (*s == '/') + { + ++s; + + char_t* name = cursor->name; + if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, s); + + while (PUGI__IS_CHARTYPE(*s, ct_symbol)) + { + if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, s); + } + + if (*name) + { + if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s); + else PUGI__THROW_ERROR(status_end_element_mismatch, s); + } + + PUGI__POPNODE(); // Pop. + + PUGI__SKIPWS(); + + if (*s == 0) + { + if (endch != '>') PUGI__THROW_ERROR(status_bad_end_element, s); + } + else + { + if (*s != '>') PUGI__THROW_ERROR(status_bad_end_element, s); + ++s; + } + } + else if (*s == '?') // 'first_child) continue; + } + } + + if (!PUGI__OPTSET(parse_trim_pcdata)) + s = mark; + + if (cursor->parent || PUGI__OPTSET(parse_fragment)) + { + PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. + cursor->value = s; // Save the offset. + + s = strconv_pcdata(s); + + PUGI__POPNODE(); // Pop since this is a standalone. + + if (!*s) break; + } + else + { + PUGI__SCANFOR(*s == '<'); // '...<' + if (!*s) break; + + ++s; + } + + // We're after '<' + goto LOC_TAG; + } + } + + // check that last tag is closed + if (cursor != root) PUGI__THROW_ERROR(status_end_element_mismatch, s); + + return s; + } + + #ifdef PUGIXML_WCHAR_MODE + static char_t* parse_skip_bom(char_t* s) + { + unsigned int bom = 0xfeff; + return (s[0] == static_cast(bom)) ? s + 1 : s; + } + #else + static char_t* parse_skip_bom(char_t* s) + { + return (s[0] == '\xef' && s[1] == '\xbb' && s[2] == '\xbf') ? s + 3 : s; + } + #endif + + static bool has_element_node_siblings(xml_node_struct* node) + { + while (node) + { + if (PUGI__NODETYPE(node) == node_element) return true; + + node = node->next_sibling; + } + + return false; + } + + static xml_parse_result parse(char_t* buffer, size_t length, xml_document_struct* xmldoc, xml_node_struct* root, unsigned int optmsk) + { + // allocator object is a part of document object + xml_allocator& alloc_ = *static_cast(xmldoc); + + // early-out for empty documents + if (length == 0) + return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element); + + // get last child of the root before parsing + xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c : 0; + + // create parser on stack + xml_parser parser(alloc_); + + // save last character and make buffer zero-terminated (speeds up parsing) + char_t endch = buffer[length - 1]; + buffer[length - 1] = 0; + + // skip BOM to make sure it does not end up as part of parse output + char_t* buffer_data = parse_skip_bom(buffer); + + // perform actual parsing + parser.parse_tree(buffer_data, root, optmsk, endch); + + // update allocator state + alloc_ = parser.alloc; + + xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0); + assert(result.offset >= 0 && static_cast(result.offset) <= length); + + if (result) + { + // since we removed last character, we have to handle the only possible false positive (stray <) + if (endch == '<') + return make_parse_result(status_unrecognized_tag, length - 1); + + // check if there are any element nodes parsed + xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling : root->first_child; + + if (!PUGI__OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed)) + return make_parse_result(status_no_document_element, length - 1); + } + else + { + // roll back offset if it occurs on a null terminator in the source buffer + if (result.offset > 0 && static_cast(result.offset) == length - 1 && endch == 0) + result.offset--; + } + + return result; + } + }; + + // Output facilities + PUGI__FN xml_encoding get_write_native_encoding() + { + #ifdef PUGIXML_WCHAR_MODE + return get_wchar_encoding(); + #else + return encoding_utf8; + #endif + } + + PUGI__FN xml_encoding get_write_encoding(xml_encoding encoding) + { + // replace wchar encoding with utf implementation + if (encoding == encoding_wchar) return get_wchar_encoding(); + + // replace utf16 encoding with utf16 with specific endianness + if (encoding == encoding_utf16) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + // replace utf32 encoding with utf32 with specific endianness + if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + // only do autodetection if no explicit encoding is requested + if (encoding != encoding_auto) return encoding; + + // assume utf8 encoding + return encoding_utf8; + } + +#ifdef PUGIXML_WCHAR_MODE + PUGI__FN size_t get_valid_length(const char_t* data, size_t length) + { + if (length < 1) return 0; + + // discard last character if it's the lead of a surrogate pair + return (sizeof(wchar_t) == 2 && static_cast(static_cast(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length; + } + + PUGI__FN size_t convert_buffer_output(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) + { + // only endian-swapping is required + if (need_endian_swap_utf(encoding, get_wchar_encoding())) + { + convert_wchar_endian_swap(r_char, data, length); + + return length * sizeof(char_t); + } + + // convert to utf8 + if (encoding == encoding_utf8) + { + uint8_t* dest = r_u8; + uint8_t* end = utf_decoder::decode_wchar_block(data, length, dest); + + return static_cast(end - dest); + } + + // convert to utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + uint16_t* dest = r_u16; + + // convert to native utf16 + uint16_t* end = utf_decoder::decode_wchar_block(data, length, dest); + + // swap if necessary + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); + + return static_cast(end - dest) * sizeof(uint16_t); + } + + // convert to utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + uint32_t* dest = r_u32; + + // convert to native utf32 + uint32_t* end = utf_decoder::decode_wchar_block(data, length, dest); + + // swap if necessary + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); + + return static_cast(end - dest) * sizeof(uint32_t); + } + + // convert to latin1 + if (encoding == encoding_latin1) + { + uint8_t* dest = r_u8; + uint8_t* end = utf_decoder::decode_wchar_block(data, length, dest); + + return static_cast(end - dest); + } + + assert(!"Invalid encoding"); + return 0; + } +#else + PUGI__FN size_t get_valid_length(const char_t* data, size_t length) + { + if (length < 5) return 0; + + for (size_t i = 1; i <= 4; ++i) + { + uint8_t ch = static_cast(data[length - i]); + + // either a standalone character or a leading one + if ((ch & 0xc0) != 0x80) return length - i; + } + + // there are four non-leading characters at the end, sequence tail is broken so might as well process the whole chunk + return length; + } + + PUGI__FN size_t convert_buffer_output(char_t* /* r_char */, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) + { + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + uint16_t* dest = r_u16; + + // convert to native utf16 + uint16_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); + + // swap if necessary + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); + + return static_cast(end - dest) * sizeof(uint16_t); + } + + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + uint32_t* dest = r_u32; + + // convert to native utf32 + uint32_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); + + // swap if necessary + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); + + return static_cast(end - dest) * sizeof(uint32_t); + } + + if (encoding == encoding_latin1) + { + uint8_t* dest = r_u8; + uint8_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); + + return static_cast(end - dest); + } + + assert(!"Invalid encoding"); + return 0; + } +#endif + + class xml_buffered_writer + { + xml_buffered_writer(const xml_buffered_writer&); + xml_buffered_writer& operator=(const xml_buffered_writer&); + + public: + xml_buffered_writer(xml_writer& writer_, xml_encoding user_encoding): writer(writer_), bufsize(0), encoding(get_write_encoding(user_encoding)) + { + PUGI__STATIC_ASSERT(bufcapacity >= 8); + } + + ~xml_buffered_writer() + { + flush(); + } + + size_t flush() + { + flush(buffer, bufsize); + bufsize = 0; + return 0; + } + + void flush(const char_t* data, size_t size) + { + if (size == 0) return; + + // fast path, just write data + if (encoding == get_write_native_encoding()) + writer.write(data, size * sizeof(char_t)); + else + { + // convert chunk + size_t result = convert_buffer_output(scratch.data_char, scratch.data_u8, scratch.data_u16, scratch.data_u32, data, size, encoding); + assert(result <= sizeof(scratch)); + + // write data + writer.write(scratch.data_u8, result); + } + } + + void write_direct(const char_t* data, size_t length) + { + // flush the remaining buffer contents + flush(); + + // handle large chunks + if (length > bufcapacity) + { + if (encoding == get_write_native_encoding()) + { + // fast path, can just write data chunk + writer.write(data, length * sizeof(char_t)); + return; + } + + // need to convert in suitable chunks + while (length > bufcapacity) + { + // get chunk size by selecting such number of characters that are guaranteed to fit into scratch buffer + // and form a complete codepoint sequence (i.e. discard start of last codepoint if necessary) + size_t chunk_size = get_valid_length(data, bufcapacity); + assert(chunk_size); + + // convert chunk and write + flush(data, chunk_size); + + // iterate + data += chunk_size; + length -= chunk_size; + } + + // small tail is copied below + bufsize = 0; + } + + memcpy(buffer + bufsize, data, length * sizeof(char_t)); + bufsize += length; + } + + void write_buffer(const char_t* data, size_t length) + { + size_t offset = bufsize; + + if (offset + length <= bufcapacity) + { + memcpy(buffer + offset, data, length * sizeof(char_t)); + bufsize = offset + length; + } + else + { + write_direct(data, length); + } + } + + void write_string(const char_t* data) + { + // write the part of the string that fits in the buffer + size_t offset = bufsize; + + while (*data && offset < bufcapacity) + buffer[offset++] = *data++; + + // write the rest + if (offset < bufcapacity) + { + bufsize = offset; + } + else + { + // backtrack a bit if we have split the codepoint + size_t length = offset - bufsize; + size_t extra = length - get_valid_length(data - length, length); + + bufsize = offset - extra; + + write_direct(data - extra, strlength(data) + extra); + } + } + + void write(char_t d0) + { + size_t offset = bufsize; + if (offset > bufcapacity - 1) offset = flush(); + + buffer[offset + 0] = d0; + bufsize = offset + 1; + } + + void write(char_t d0, char_t d1) + { + size_t offset = bufsize; + if (offset > bufcapacity - 2) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + bufsize = offset + 2; + } + + void write(char_t d0, char_t d1, char_t d2) + { + size_t offset = bufsize; + if (offset > bufcapacity - 3) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + buffer[offset + 2] = d2; + bufsize = offset + 3; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3) + { + size_t offset = bufsize; + if (offset > bufcapacity - 4) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + buffer[offset + 2] = d2; + buffer[offset + 3] = d3; + bufsize = offset + 4; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4) + { + size_t offset = bufsize; + if (offset > bufcapacity - 5) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + buffer[offset + 2] = d2; + buffer[offset + 3] = d3; + buffer[offset + 4] = d4; + bufsize = offset + 5; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5) + { + size_t offset = bufsize; + if (offset > bufcapacity - 6) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + buffer[offset + 2] = d2; + buffer[offset + 3] = d3; + buffer[offset + 4] = d4; + buffer[offset + 5] = d5; + bufsize = offset + 6; + } + + // utf8 maximum expansion: x4 (-> utf32) + // utf16 maximum expansion: x2 (-> utf32) + // utf32 maximum expansion: x1 + enum + { + bufcapacitybytes = + #ifdef PUGIXML_MEMORY_OUTPUT_STACK + PUGIXML_MEMORY_OUTPUT_STACK + #else + 10240 + #endif + , + bufcapacity = bufcapacitybytes / (sizeof(char_t) + 4) + }; + + char_t buffer[bufcapacity]; + + union + { + uint8_t data_u8[4 * bufcapacity]; + uint16_t data_u16[2 * bufcapacity]; + uint32_t data_u32[bufcapacity]; + char_t data_char[bufcapacity]; + } scratch; + + xml_writer& writer; + size_t bufsize; + xml_encoding encoding; + }; + + PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type) + { + while (*s) + { + const char_t* prev = s; + + // While *s is a usual symbol + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type)); + + writer.write_buffer(prev, static_cast(s - prev)); + + switch (*s) + { + case 0: break; + case '&': + writer.write('&', 'a', 'm', 'p', ';'); + ++s; + break; + case '<': + writer.write('&', 'l', 't', ';'); + ++s; + break; + case '>': + writer.write('&', 'g', 't', ';'); + ++s; + break; + case '"': + writer.write('&', 'q', 'u', 'o', 't', ';'); + ++s; + break; + default: // s is not a usual symbol + { + unsigned int ch = static_cast(*s++); + assert(ch < 32); + + writer.write('&', '#', static_cast((ch / 10) + '0'), static_cast((ch % 10) + '0'), ';'); + } + } + } + } + + PUGI__FN void text_output(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) + { + if (flags & format_no_escapes) + writer.write_string(s); + else + text_output_escaped(writer, s, type); + } + + PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s) + { + do + { + writer.write('<', '!', '[', 'C', 'D'); + writer.write('A', 'T', 'A', '['); + + const char_t* prev = s; + + // look for ]]> sequence - we can't output it as is since it terminates CDATA + while (*s && !(s[0] == ']' && s[1] == ']' && s[2] == '>')) ++s; + + // skip ]] if we stopped at ]]>, > will go to the next CDATA section + if (*s) s += 2; + + writer.write_buffer(prev, static_cast(s - prev)); + + writer.write(']', ']', '>'); + } + while (*s); + } + + PUGI__FN void text_output_indent(xml_buffered_writer& writer, const char_t* indent, size_t indent_length, unsigned int depth) + { + switch (indent_length) + { + case 1: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write(indent[0]); + break; + } + + case 2: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write(indent[0], indent[1]); + break; + } + + case 3: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write(indent[0], indent[1], indent[2]); + break; + } + + case 4: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write(indent[0], indent[1], indent[2], indent[3]); + break; + } + + default: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write_buffer(indent, indent_length); + } + } + } + + PUGI__FN void node_output_comment(xml_buffered_writer& writer, const char_t* s) + { + writer.write('<', '!', '-', '-'); + + while (*s) + { + const char_t* prev = s; + + // look for -\0 or -- sequence - we can't output it since -- is illegal in comment body + while (*s && !(s[0] == '-' && (s[1] == '-' || s[1] == 0))) ++s; + + writer.write_buffer(prev, static_cast(s - prev)); + + if (*s) + { + assert(*s == '-'); + + writer.write('-', ' '); + ++s; + } + } + + writer.write('-', '-', '>'); + } + + PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + + for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) + { + writer.write(' '); + writer.write_string(a->name ? a->name : default_name); + writer.write('=', '"'); + + if (a->value) + text_output(writer, a->value, ctx_special_attr, flags); + + writer.write('"'); + } + } + + PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + const char_t* name = node->name ? node->name : default_name; + + writer.write('<'); + writer.write_string(name); + + if (node->first_attribute) + node_output_attributes(writer, node, flags); + + if (flags & format_raw) + { + if (!node->first_child) + writer.write(' ', '/', '>'); + else + { + writer.write('>'); + + return true; + } + } + else + { + xml_node_struct* first = node->first_child; + + if (!first) + writer.write(' ', '/', '>', '\n'); + else if (!first->next_sibling && (PUGI__NODETYPE(first) == node_pcdata || PUGI__NODETYPE(first) == node_cdata)) + { + writer.write('>'); + + const char_t* value = first->value ? first->value : PUGIXML_TEXT(""); + + if (PUGI__NODETYPE(first) == node_pcdata) + text_output(writer, value, ctx_special_pcdata, flags); + else + text_output_cdata(writer, value); + + writer.write('<', '/'); + writer.write_string(name); + writer.write('>', '\n'); + } + else + { + writer.write('>', '\n'); + + return true; + } + } + + return false; + } + + PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + const char_t* name = node->name ? node->name : default_name; + + writer.write('<', '/'); + writer.write_string(name); + + if (flags & format_raw) + writer.write('>'); + else + writer.write('>', '\n'); + } + + PUGI__FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + + switch (PUGI__NODETYPE(node)) + { + case node_pcdata: + text_output(writer, node->value ? node->value : PUGIXML_TEXT(""), ctx_special_pcdata, flags); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_cdata: + text_output_cdata(writer, node->value ? node->value : PUGIXML_TEXT("")); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_comment: + node_output_comment(writer, node->value ? node->value : PUGIXML_TEXT("")); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_pi: + writer.write('<', '?'); + writer.write_string(node->name ? node->name : default_name); + + if (node->value) + { + writer.write(' '); + writer.write_string(node->value); + } + + writer.write('?', '>'); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_declaration: + writer.write('<', '?'); + writer.write_string(node->name ? node->name : default_name); + node_output_attributes(writer, node, flags); + writer.write('?', '>'); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_doctype: + writer.write('<', '!', 'D', 'O', 'C'); + writer.write('T', 'Y', 'P', 'E'); + + if (node->value) + { + writer.write(' '); + writer.write_string(node->value); + } + + writer.write('>'); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + default: + assert(!"Invalid node type"); + } + } + + PUGI__FN void node_output(xml_buffered_writer& writer, xml_node_struct* root, const char_t* indent, unsigned int flags, unsigned int depth) + { + size_t indent_length = ((flags & (format_indent | format_raw)) == format_indent) ? strlength(indent) : 0; + + xml_node_struct* node = root; + + do + { + assert(node); + + // begin writing current node + if (indent_length) + text_output_indent(writer, indent, indent_length, depth); + + if (PUGI__NODETYPE(node) == node_element) + { + if (node_output_start(writer, node, flags)) + { + node = node->first_child; + depth++; + continue; + } + } + else if (PUGI__NODETYPE(node) == node_document) + { + if (node->first_child) + { + node = node->first_child; + continue; + } + } + else + { + node_output_simple(writer, node, flags); + } + + // continue to the next node + while (node != root) + { + if (node->next_sibling) + { + node = node->next_sibling; + break; + } + + node = node->parent; + + // write closing node + if (PUGI__NODETYPE(node) == node_element) + { + depth--; + + if (indent_length) + text_output_indent(writer, indent, indent_length, depth); + + node_output_end(writer, node, flags); + } + } + } + while (node != root); + } + + PUGI__FN bool has_declaration(xml_node_struct* node) + { + for (xml_node_struct* child = node->first_child; child; child = child->next_sibling) + { + xml_node_type type = PUGI__NODETYPE(child); + + if (type == node_declaration) return true; + if (type == node_element) return false; + } + + return false; + } + + PUGI__FN bool is_attribute_of(xml_attribute_struct* attr, xml_node_struct* node) + { + for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) + if (a == attr) + return true; + + return false; + } + + PUGI__FN bool allow_insert_attribute(xml_node_type parent) + { + return parent == node_element || parent == node_declaration; + } + + PUGI__FN bool allow_insert_child(xml_node_type parent, xml_node_type child) + { + if (parent != node_document && parent != node_element) return false; + if (child == node_document || child == node_null) return false; + if (parent != node_document && (child == node_declaration || child == node_doctype)) return false; + + return true; + } + + PUGI__FN bool allow_move(xml_node parent, xml_node child) + { + // check that child can be a child of parent + if (!allow_insert_child(parent.type(), child.type())) + return false; + + // check that node is not moved between documents + if (parent.root() != child.root()) + return false; + + // check that new parent is not in the child subtree + xml_node cur = parent; + + while (cur) + { + if (cur == child) + return false; + + cur = cur.parent(); + } + + return true; + } + + PUGI__FN void node_copy_string(char_t*& dest, uintptr_t& header, uintptr_t header_mask, char_t* source, uintptr_t& source_header, xml_allocator* alloc) + { + assert(!dest && (header & header_mask) == 0); + + if (source) + { + if (alloc && (source_header & header_mask) == 0) + { + dest = source; + + // since strcpy_insitu can reuse document buffer memory we need to mark both source and dest as shared + header |= xml_memory_page_contents_shared_mask; + source_header |= xml_memory_page_contents_shared_mask; + } + else + strcpy_insitu(dest, header, header_mask, source); + } + } + + PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc) + { + node_copy_string(dn->name, dn->header, xml_memory_page_name_allocated_mask, sn->name, sn->header, shared_alloc); + node_copy_string(dn->value, dn->header, xml_memory_page_value_allocated_mask, sn->value, sn->header, shared_alloc); + + for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute) + { + xml_attribute_struct* da = append_new_attribute(dn, get_allocator(dn)); + + if (da) + { + node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc); + node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc); + } + } + } + + PUGI__FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn) + { + xml_allocator& alloc = get_allocator(dn); + xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : 0; + + node_copy_contents(dn, sn, shared_alloc); + + xml_node_struct* dit = dn; + xml_node_struct* sit = sn->first_child; + + while (sit && sit != sn) + { + if (sit != dn) + { + xml_node_struct* copy = append_new_node(dit, alloc, PUGI__NODETYPE(sit)); + + if (copy) + { + node_copy_contents(copy, sit, shared_alloc); + + if (sit->first_child) + { + dit = copy; + sit = sit->first_child; + continue; + } + } + } + + // continue to the next node + do + { + if (sit->next_sibling) + { + sit = sit->next_sibling; + break; + } + + sit = sit->parent; + dit = dit->parent; + } + while (sit != sn); + } + } + + inline bool is_text_node(xml_node_struct* node) + { + xml_node_type type = PUGI__NODETYPE(node); + + return type == node_pcdata || type == node_cdata; + } + + // get value with conversion functions + PUGI__FN int get_integer_base(const char_t* value) + { + const char_t* s = value; + + while (PUGI__IS_CHARTYPE(*s, ct_space)) + s++; + + if (*s == '-') + s++; + + return (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10; + } + + PUGI__FN int get_value_int(const char_t* value, int def) + { + if (!value) return def; + + int base = get_integer_base(value); + + #ifdef PUGIXML_WCHAR_MODE + return static_cast(wcstol(value, 0, base)); + #else + return static_cast(strtol(value, 0, base)); + #endif + } + + PUGI__FN unsigned int get_value_uint(const char_t* value, unsigned int def) + { + if (!value) return def; + + int base = get_integer_base(value); + + #ifdef PUGIXML_WCHAR_MODE + return static_cast(wcstoul(value, 0, base)); + #else + return static_cast(strtoul(value, 0, base)); + #endif + } + + PUGI__FN double get_value_double(const char_t* value, double def) + { + if (!value) return def; + + #ifdef PUGIXML_WCHAR_MODE + return wcstod(value, 0); + #else + return strtod(value, 0); + #endif + } + + PUGI__FN float get_value_float(const char_t* value, float def) + { + if (!value) return def; + + #ifdef PUGIXML_WCHAR_MODE + return static_cast(wcstod(value, 0)); + #else + return static_cast(strtod(value, 0)); + #endif + } + + PUGI__FN bool get_value_bool(const char_t* value, bool def) + { + if (!value) return def; + + // only look at first char + char_t first = *value; + + // 1*, t* (true), T* (True), y* (yes), Y* (YES) + return (first == '1' || first == 't' || first == 'T' || first == 'y' || first == 'Y'); + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long get_value_llong(const char_t* value, long long def) + { + if (!value) return def; + + int base = get_integer_base(value); + + #ifdef PUGIXML_WCHAR_MODE + #ifdef PUGI__MSVC_CRT_VERSION + return _wcstoi64(value, 0, base); + #else + return wcstoll(value, 0, base); + #endif + #else + #ifdef PUGI__MSVC_CRT_VERSION + return _strtoi64(value, 0, base); + #else + return strtoll(value, 0, base); + #endif + #endif + } + + PUGI__FN unsigned long long get_value_ullong(const char_t* value, unsigned long long def) + { + if (!value) return def; + + int base = get_integer_base(value); + + #ifdef PUGIXML_WCHAR_MODE + #ifdef PUGI__MSVC_CRT_VERSION + return _wcstoui64(value, 0, base); + #else + return wcstoull(value, 0, base); + #endif + #else + #ifdef PUGI__MSVC_CRT_VERSION + return _strtoui64(value, 0, base); + #else + return strtoull(value, 0, base); + #endif + #endif + } +#endif + + // set value with conversion functions + PUGI__FN bool set_value_buffer(char_t*& dest, uintptr_t& header, uintptr_t header_mask, char (&buf)[128]) + { + #ifdef PUGIXML_WCHAR_MODE + char_t wbuf[128]; + impl::widen_ascii(wbuf, buf); + + return strcpy_insitu(dest, header, header_mask, wbuf); + #else + return strcpy_insitu(dest, header, header_mask, buf); + #endif + } + + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, int value) + { + char buf[128]; + sprintf(buf, "%d", value); + + return set_value_buffer(dest, header, header_mask, buf); + } + + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, unsigned int value) + { + char buf[128]; + sprintf(buf, "%u", value); + + return set_value_buffer(dest, header, header_mask, buf); + } + + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, float value) + { + char buf[128]; + sprintf(buf, "%.9g", value); + + return set_value_buffer(dest, header, header_mask, buf); + } + + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, double value) + { + char buf[128]; + sprintf(buf, "%.17g", value); + + return set_value_buffer(dest, header, header_mask, buf); + } + + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, bool value) + { + return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, long long value) + { + char buf[128]; + sprintf(buf, "%lld", value); + + return set_value_buffer(dest, header, header_mask, buf); + } + + PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, unsigned long long value) + { + char buf[128]; + sprintf(buf, "%llu", value); + + return set_value_buffer(dest, header, header_mask, buf); + } +#endif + + // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick + PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) + { + #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) + // there are 64-bit versions of fseek/ftell, let's use them + typedef __int64 length_type; + + _fseeki64(file, 0, SEEK_END); + length_type length = _ftelli64(file); + _fseeki64(file, 0, SEEK_SET); + #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)) + // there are 64-bit versions of fseek/ftell, let's use them + typedef off64_t length_type; + + fseeko64(file, 0, SEEK_END); + length_type length = ftello64(file); + fseeko64(file, 0, SEEK_SET); + #else + // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. + typedef long length_type; + + fseek(file, 0, SEEK_END); + length_type length = ftell(file); + fseek(file, 0, SEEK_SET); + #endif + + // check for I/O errors + if (length < 0) return status_io_error; + + // check for overflow + size_t result = static_cast(length); + + if (static_cast(result) != length) return status_out_of_memory; + + // finalize + out_result = result; + + return status_ok; + } + + PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding) + { + // We only need to zero-terminate if encoding conversion does not do it for us + #ifdef PUGIXML_WCHAR_MODE + xml_encoding wchar_encoding = get_wchar_encoding(); + + if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding)) + { + size_t length = size / sizeof(char_t); + + static_cast(buffer)[length] = 0; + return (length + 1) * sizeof(char_t); + } + #else + if (encoding == encoding_utf8) + { + static_cast(buffer)[size] = 0; + return size + 1; + } + #endif + + return size; + } + + PUGI__FN xml_parse_result load_file_impl(xml_document& doc, FILE* file, unsigned int options, xml_encoding encoding) + { + if (!file) return make_parse_result(status_file_not_found); + + // get file size (can result in I/O errors) + size_t size = 0; + xml_parse_status size_status = get_file_size(file, size); + + if (size_status != status_ok) + { + fclose(file); + return make_parse_result(size_status); + } + + size_t max_suffix_size = sizeof(char_t); + + // allocate buffer for the whole file + char* contents = static_cast(xml_memory::allocate(size + max_suffix_size)); + + if (!contents) + { + fclose(file); + return make_parse_result(status_out_of_memory); + } + + // read file in memory + size_t read_size = fread(contents, 1, size, file); + fclose(file); + + if (read_size != size) + { + xml_memory::deallocate(contents); + return make_parse_result(status_io_error); + } + + xml_encoding real_encoding = get_buffer_encoding(encoding, contents, size); + + return doc.load_buffer_inplace_own(contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding); + } + +#ifndef PUGIXML_NO_STL + template struct xml_stream_chunk + { + static xml_stream_chunk* create() + { + void* memory = xml_memory::allocate(sizeof(xml_stream_chunk)); + + return new (memory) xml_stream_chunk(); + } + + static void destroy(void* ptr) + { + xml_stream_chunk* chunk = static_cast(ptr); + + // free chunk chain + while (chunk) + { + xml_stream_chunk* next_ = chunk->next; + + xml_memory::deallocate(chunk); + + chunk = next_; + } + } + + xml_stream_chunk(): next(0), size(0) + { + } + + xml_stream_chunk* next; + size_t size; + + T data[xml_memory_page_size / sizeof(T)]; + }; + + template PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream& stream, void** out_buffer, size_t* out_size) + { + buffer_holder chunks(0, xml_stream_chunk::destroy); + + // read file to a chunk list + size_t total = 0; + xml_stream_chunk* last = 0; + + while (!stream.eof()) + { + // allocate new chunk + xml_stream_chunk* chunk = xml_stream_chunk::create(); + if (!chunk) return status_out_of_memory; + + // append chunk to list + if (last) last = last->next = chunk; + else chunks.data = last = chunk; + + // read data to chunk + stream.read(chunk->data, static_cast(sizeof(chunk->data) / sizeof(T))); + chunk->size = static_cast(stream.gcount()) * sizeof(T); + + // read may set failbit | eofbit in case gcount() is less than read length, so check for other I/O errors + if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; + + // guard against huge files (chunk size is small enough to make this overflow check work) + if (total + chunk->size < total) return status_out_of_memory; + total += chunk->size; + } + + size_t max_suffix_size = sizeof(char_t); + + // copy chunk list to a contiguous buffer + char* buffer = static_cast(xml_memory::allocate(total + max_suffix_size)); + if (!buffer) return status_out_of_memory; + + char* write = buffer; + + for (xml_stream_chunk* chunk = static_cast*>(chunks.data); chunk; chunk = chunk->next) + { + assert(write + chunk->size <= buffer + total); + memcpy(write, chunk->data, chunk->size); + write += chunk->size; + } + + assert(write == buffer + total); + + // return buffer + *out_buffer = buffer; + *out_size = total; + + return status_ok; + } + + template PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream& stream, void** out_buffer, size_t* out_size) + { + // get length of remaining data in stream + typename std::basic_istream::pos_type pos = stream.tellg(); + stream.seekg(0, std::ios::end); + std::streamoff length = stream.tellg() - pos; + stream.seekg(pos); + + if (stream.fail() || pos < 0) return status_io_error; + + // guard against huge files + size_t read_length = static_cast(length); + + if (static_cast(read_length) != length || length < 0) return status_out_of_memory; + + size_t max_suffix_size = sizeof(char_t); + + // read stream data into memory (guard against stream exceptions with buffer holder) + buffer_holder buffer(xml_memory::allocate(read_length * sizeof(T) + max_suffix_size), xml_memory::deallocate); + if (!buffer.data) return status_out_of_memory; + + stream.read(static_cast(buffer.data), static_cast(read_length)); + + // read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors + if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; + + // return buffer + size_t actual_length = static_cast(stream.gcount()); + assert(actual_length <= read_length); + + *out_buffer = buffer.release(); + *out_size = actual_length * sizeof(T); + + return status_ok; + } + + template PUGI__FN xml_parse_result load_stream_impl(xml_document& doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding) + { + void* buffer = 0; + size_t size = 0; + xml_parse_status status = status_ok; + + // if stream has an error bit set, bail out (otherwise tellg() can fail and we'll clear error bits) + if (stream.fail()) return make_parse_result(status_io_error); + + // load stream to memory (using seek-based implementation if possible, since it's faster and takes less memory) + if (stream.tellg() < 0) + { + stream.clear(); // clear error flags that could be set by a failing tellg + status = load_stream_data_noseek(stream, &buffer, &size); + } + else + status = load_stream_data_seek(stream, &buffer, &size); + + if (status != status_ok) return make_parse_result(status); + + xml_encoding real_encoding = get_buffer_encoding(encoding, buffer, size); + + return doc.load_buffer_inplace_own(buffer, zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding); + } +#endif + +#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) + PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) + { + return _wfopen(path, mode); + } +#else + PUGI__FN char* convert_path_heap(const wchar_t* str) + { + assert(str); + + // first pass: get length in utf8 characters + size_t length = strlength_wide(str); + size_t size = as_utf8_begin(str, length); + + // allocate resulting string + char* result = static_cast(xml_memory::allocate(size + 1)); + if (!result) return 0; + + // second pass: convert to utf8 + as_utf8_end(result, size, str, length); + + return result; + } + + PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) + { + // there is no standard function to open wide paths, so our best bet is to try utf8 path + char* path_utf8 = convert_path_heap(path); + if (!path_utf8) return 0; + + // convert mode to ASCII (we mirror _wfopen interface) + char mode_ascii[4] = {0}; + for (size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast(mode[i]); + + // try to open the utf8 path + FILE* result = fopen(path_utf8, mode_ascii); + + // free dummy buffer + xml_memory::deallocate(path_utf8); + + return result; + } +#endif + + PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) + { + if (!file) return false; + + xml_writer_file writer(file); + doc.save(writer, indent, flags, encoding); + + int result = ferror(file); + + fclose(file); + + return result == 0; + } + + PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer) + { + // check input buffer + assert(contents || size == 0); + + // get actual encoding + xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size); + + // get private buffer + char_t* buffer = 0; + size_t length = 0; + + if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); + + // delete original buffer if we performed a conversion + if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents); + + // store buffer for offset_debug + doc->buffer = buffer; + + // parse + xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options); + + // remember encoding + res.encoding = buffer_encoding; + + // grab onto buffer if it's our buffer, user is responsible for deallocating contents himself + if (own || buffer != contents) *out_buffer = buffer; + + return res; + } +PUGI__NS_END + +namespace pugi +{ + PUGI__FN xml_writer_file::xml_writer_file(void* file_): file(file_) + { + } + + PUGI__FN void xml_writer_file::write(const void* data, size_t size) + { + size_t result = fwrite(data, 1, size, static_cast(file)); + (void)!result; // unfortunately we can't do proper error handling here + } + +#ifndef PUGIXML_NO_STL + PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) + { + } + + PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) + { + } + + PUGI__FN void xml_writer_stream::write(const void* data, size_t size) + { + if (narrow_stream) + { + assert(!wide_stream); + narrow_stream->write(reinterpret_cast(data), static_cast(size)); + } + else + { + assert(wide_stream); + assert(size % sizeof(wchar_t) == 0); + + wide_stream->write(reinterpret_cast(data), static_cast(size / sizeof(wchar_t))); + } + } +#endif + + PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0) + { + } + + PUGI__FN xml_tree_walker::~xml_tree_walker() + { + } + + PUGI__FN int xml_tree_walker::depth() const + { + return _depth; + } + + PUGI__FN bool xml_tree_walker::begin(xml_node&) + { + return true; + } + + PUGI__FN bool xml_tree_walker::end(xml_node&) + { + return true; + } + + PUGI__FN xml_attribute::xml_attribute(): _attr(0) + { + } + + PUGI__FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr) + { + } + + PUGI__FN static void unspecified_bool_xml_attribute(xml_attribute***) + { + } + + PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type() const + { + return _attr ? unspecified_bool_xml_attribute : 0; + } + + PUGI__FN bool xml_attribute::operator!() const + { + return !_attr; + } + + PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const + { + return (_attr == r._attr); + } + + PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const + { + return (_attr != r._attr); + } + + PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const + { + return (_attr < r._attr); + } + + PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const + { + return (_attr > r._attr); + } + + PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const + { + return (_attr <= r._attr); + } + + PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const + { + return (_attr >= r._attr); + } + + PUGI__FN xml_attribute xml_attribute::next_attribute() const + { + return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); + } + + PUGI__FN xml_attribute xml_attribute::previous_attribute() const + { + return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); + } + + PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const + { + return (_attr && _attr->value) ? _attr->value : def; + } + + PUGI__FN int xml_attribute::as_int(int def) const + { + return impl::get_value_int(_attr ? _attr->value : 0, def); + } + + PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const + { + return impl::get_value_uint(_attr ? _attr->value : 0, def); + } + + PUGI__FN double xml_attribute::as_double(double def) const + { + return impl::get_value_double(_attr ? _attr->value : 0, def); + } + + PUGI__FN float xml_attribute::as_float(float def) const + { + return impl::get_value_float(_attr ? _attr->value : 0, def); + } + + PUGI__FN bool xml_attribute::as_bool(bool def) const + { + return impl::get_value_bool(_attr ? _attr->value : 0, def); + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long xml_attribute::as_llong(long long def) const + { + return impl::get_value_llong(_attr ? _attr->value : 0, def); + } + + PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const + { + return impl::get_value_ullong(_attr ? _attr->value : 0, def); + } +#endif + + PUGI__FN bool xml_attribute::empty() const + { + return !_attr; + } + + PUGI__FN const char_t* xml_attribute::name() const + { + return (_attr && _attr->name) ? _attr->name : PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* xml_attribute::value() const + { + return (_attr && _attr->value) ? _attr->value : PUGIXML_TEXT(""); + } + + PUGI__FN size_t xml_attribute::hash_value() const + { + return static_cast(reinterpret_cast(_attr) / sizeof(xml_attribute_struct)); + } + + PUGI__FN xml_attribute_struct* xml_attribute::internal_object() const + { + return _attr; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(int rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(unsigned int rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(double rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(float rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs) + { + set_value(rhs); + return *this; + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long long rhs) + { + set_value(rhs); + return *this; + } +#endif + + PUGI__FN bool xml_attribute::set_name(const char_t* rhs) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs); + } + + PUGI__FN bool xml_attribute::set_value(const char_t* rhs) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + + PUGI__FN bool xml_attribute::set_value(int rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + + PUGI__FN bool xml_attribute::set_value(unsigned int rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + + PUGI__FN bool xml_attribute::set_value(double rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + + PUGI__FN bool xml_attribute::set_value(float rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + + PUGI__FN bool xml_attribute::set_value(bool rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN bool xml_attribute::set_value(long long rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + + PUGI__FN bool xml_attribute::set_value(unsigned long long rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } +#endif + +#ifdef __BORLANDC__ + PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + PUGI__FN bool operator||(const xml_attribute& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + PUGI__FN xml_node::xml_node(): _root(0) + { + } + + PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p) + { + } + + PUGI__FN static void unspecified_bool_xml_node(xml_node***) + { + } + + PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const + { + return _root ? unspecified_bool_xml_node : 0; + } + + PUGI__FN bool xml_node::operator!() const + { + return !_root; + } + + PUGI__FN xml_node::iterator xml_node::begin() const + { + return iterator(_root ? _root->first_child : 0, _root); + } + + PUGI__FN xml_node::iterator xml_node::end() const + { + return iterator(0, _root); + } + + PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const + { + return attribute_iterator(_root ? _root->first_attribute : 0, _root); + } + + PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const + { + return attribute_iterator(0, _root); + } + + PUGI__FN xml_object_range xml_node::children() const + { + return xml_object_range(begin(), end()); + } + + PUGI__FN xml_object_range xml_node::children(const char_t* name_) const + { + return xml_object_range(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_)); + } + + PUGI__FN xml_object_range xml_node::attributes() const + { + return xml_object_range(attributes_begin(), attributes_end()); + } + + PUGI__FN bool xml_node::operator==(const xml_node& r) const + { + return (_root == r._root); + } + + PUGI__FN bool xml_node::operator!=(const xml_node& r) const + { + return (_root != r._root); + } + + PUGI__FN bool xml_node::operator<(const xml_node& r) const + { + return (_root < r._root); + } + + PUGI__FN bool xml_node::operator>(const xml_node& r) const + { + return (_root > r._root); + } + + PUGI__FN bool xml_node::operator<=(const xml_node& r) const + { + return (_root <= r._root); + } + + PUGI__FN bool xml_node::operator>=(const xml_node& r) const + { + return (_root >= r._root); + } + + PUGI__FN bool xml_node::empty() const + { + return !_root; + } + + PUGI__FN const char_t* xml_node::name() const + { + return (_root && _root->name) ? _root->name : PUGIXML_TEXT(""); + } + + PUGI__FN xml_node_type xml_node::type() const + { + return _root ? PUGI__NODETYPE(_root) : node_null; + } + + PUGI__FN const char_t* xml_node::value() const + { + return (_root && _root->value) ? _root->value : PUGIXML_TEXT(""); + } + + PUGI__FN xml_node xml_node::child(const char_t* name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + + return xml_node(); + } + + PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const + { + if (!_root) return xml_attribute(); + + for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) + if (i->name && impl::strequal(name_, i->name)) + return xml_attribute(i); + + return xml_attribute(); + } + + PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) + if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + + return xml_node(); + } + + PUGI__FN xml_node xml_node::next_sibling() const + { + return _root ? xml_node(_root->next_sibling) : xml_node(); + } + + PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) + if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + + return xml_node(); + } + + PUGI__FN xml_node xml_node::previous_sibling() const + { + if (!_root) return xml_node(); + + if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); + else return xml_node(); + } + + PUGI__FN xml_node xml_node::parent() const + { + return _root ? xml_node(_root->parent) : xml_node(); + } + + PUGI__FN xml_node xml_node::root() const + { + return _root ? xml_node(&impl::get_document(_root)) : xml_node(); + } + + PUGI__FN xml_text xml_node::text() const + { + return xml_text(_root); + } + + PUGI__FN const char_t* xml_node::child_value() const + { + if (!_root) return PUGIXML_TEXT(""); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (i->value && impl::is_text_node(i)) + return i->value; + + return PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const + { + return child(name_).child_value(); + } + + PUGI__FN xml_attribute xml_node::first_attribute() const + { + return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); + } + + PUGI__FN xml_attribute xml_node::last_attribute() const + { + return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); + } + + PUGI__FN xml_node xml_node::first_child() const + { + return _root ? xml_node(_root->first_child) : xml_node(); + } + + PUGI__FN xml_node xml_node::last_child() const + { + return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); + } + + PUGI__FN bool xml_node::set_name(const char_t* rhs) + { + switch (type()) + { + case node_pi: + case node_declaration: + case node_element: + return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs); + + default: + return false; + } + } + + PUGI__FN bool xml_node::set_value(const char_t* rhs) + { + switch (type()) + { + case node_pi: + case node_cdata: + case node_pcdata: + case node_comment: + case node_doctype: + return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs); + + default: + return false; + } + } + + PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); + if (!a) return xml_attribute(); + + impl::append_attribute(a._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); + if (!a) return xml_attribute(); + + impl::prepend_attribute(a._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); + if (!a) return xml_attribute(); + + impl::insert_attribute_after(a._attr, attr._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); + if (!a) return xml_attribute(); + + impl::insert_attribute_before(a._attr, attr._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto) + { + if (!proto) return xml_attribute(); + + xml_attribute result = append_attribute(proto.name()); + result.set_value(proto.value()); + + return result; + } + + PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto) + { + if (!proto) return xml_attribute(); + + xml_attribute result = prepend_attribute(proto.name()); + result.set_value(proto.value()); + + return result; + } + + PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr) + { + if (!proto) return xml_attribute(); + + xml_attribute result = insert_attribute_after(proto.name(), attr); + result.set_value(proto.value()); + + return result; + } + + PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr) + { + if (!proto) return xml_attribute(); + + xml_attribute result = insert_attribute_before(proto.name(), attr); + result.set_value(proto.value()); + + return result; + } + + PUGI__FN xml_node xml_node::append_child(xml_node_type type_) + { + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); + + impl::append_node(n._root, _root); + + if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_) + { + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); + + impl::prepend_node(n._root, _root); + + if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node) + { + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); + + impl::insert_node_before(n._root, node._root); + + if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node) + { + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); + + impl::insert_node_after(n._root, node._root); + + if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + PUGI__FN xml_node xml_node::append_child(const char_t* name_) + { + xml_node result = append_child(node_element); + + result.set_name(name_); + + return result; + } + + PUGI__FN xml_node xml_node::prepend_child(const char_t* name_) + { + xml_node result = prepend_child(node_element); + + result.set_name(name_); + + return result; + } + + PUGI__FN xml_node xml_node::insert_child_after(const char_t* name_, const xml_node& node) + { + xml_node result = insert_child_after(node_element, node); + + result.set_name(name_); + + return result; + } + + PUGI__FN xml_node xml_node::insert_child_before(const char_t* name_, const xml_node& node) + { + xml_node result = insert_child_before(node_element, node); + + result.set_name(name_); + + return result; + } + + PUGI__FN xml_node xml_node::append_copy(const xml_node& proto) + { + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); + + impl::append_node(n._root, _root); + impl::node_copy_tree(n._root, proto._root); + + return n; + } + + PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto) + { + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); + + impl::prepend_node(n._root, _root); + impl::node_copy_tree(n._root, proto._root); + + return n; + } + + PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) + { + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); + + impl::insert_node_after(n._root, node._root); + impl::node_copy_tree(n._root, proto._root); + + return n; + } + + PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) + { + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); + + impl::insert_node_before(n._root, node._root); + impl::node_copy_tree(n._root, proto._root); + + return n; + } + + PUGI__FN xml_node xml_node::append_move(const xml_node& moved) + { + if (!impl::allow_move(*this, moved)) return xml_node(); + + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; + + impl::remove_node(moved._root); + impl::append_node(moved._root, _root); + + return moved; + } + + PUGI__FN xml_node xml_node::prepend_move(const xml_node& moved) + { + if (!impl::allow_move(*this, moved)) return xml_node(); + + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; + + impl::remove_node(moved._root); + impl::prepend_node(moved._root, _root); + + return moved; + } + + PUGI__FN xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node) + { + if (!impl::allow_move(*this, moved)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + if (moved._root == node._root) return xml_node(); + + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; + + impl::remove_node(moved._root); + impl::insert_node_after(moved._root, node._root); + + return moved; + } + + PUGI__FN xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node) + { + if (!impl::allow_move(*this, moved)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + if (moved._root == node._root) return xml_node(); + + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; + + impl::remove_node(moved._root); + impl::insert_node_before(moved._root, node._root); + + return moved; + } + + PUGI__FN bool xml_node::remove_attribute(const char_t* name_) + { + return remove_attribute(attribute(name_)); + } + + PUGI__FN bool xml_node::remove_attribute(const xml_attribute& a) + { + if (!_root || !a._attr) return false; + if (!impl::is_attribute_of(a._attr, _root)) return false; + + impl::remove_attribute(a._attr, _root); + impl::destroy_attribute(a._attr, impl::get_allocator(_root)); + + return true; + } + + PUGI__FN bool xml_node::remove_child(const char_t* name_) + { + return remove_child(child(name_)); + } + + PUGI__FN bool xml_node::remove_child(const xml_node& n) + { + if (!_root || !n._root || n._root->parent != _root) return false; + + impl::remove_node(n._root); + impl::destroy_node(n._root, impl::get_allocator(_root)); + + return true; + } + + PUGI__FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + // append_buffer is only valid for elements/documents + if (!impl::allow_insert_child(type(), node_element)) return impl::make_parse_result(status_append_invalid_root); + + // get document node + impl::xml_document_struct* doc = &impl::get_document(_root); + + // disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense + doc->header |= impl::xml_memory_page_contents_shared_mask; + + // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later) + impl::xml_memory_page* page = 0; + impl::xml_extra_buffer* extra = static_cast(doc->allocate_memory(sizeof(impl::xml_extra_buffer), page)); + (void)page; + + if (!extra) return impl::make_parse_result(status_out_of_memory); + + // save name; name of the root has to be NULL before parsing - otherwise closing node mismatches will not be detected at the top level + char_t* rootname = _root->name; + _root->name = 0; + + // parse + char_t* buffer = 0; + xml_parse_result res = impl::load_buffer_impl(doc, _root, const_cast(contents), size, options, encoding, false, false, &buffer); + + // restore name + _root->name = rootname; + + // add extra buffer to the list + extra->buffer = buffer; + extra->next = doc->extra_buffers; + doc->extra_buffers = extra; + + return res; + } + + PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (i->name && impl::strequal(name_, i->name)) + { + for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) + if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value : PUGIXML_TEXT(""))) + return xml_node(i); + } + + return xml_node(); + } + + PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) + if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value : PUGIXML_TEXT(""))) + return xml_node(i); + + return xml_node(); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN string_t xml_node::path(char_t delimiter) const + { + xml_node cursor = *this; // Make a copy. + + string_t result = cursor.name(); + + while (cursor.parent()) + { + cursor = cursor.parent(); + + string_t temp = cursor.name(); + temp += delimiter; + temp += result; + result.swap(temp); + } + + return result; + } +#endif + + PUGI__FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const + { + xml_node found = *this; // Current search context. + + if (!_root || !path_ || !path_[0]) return found; + + if (path_[0] == delimiter) + { + // Absolute path; e.g. '/foo/bar' + found = found.root(); + ++path_; + } + + const char_t* path_segment = path_; + + while (*path_segment == delimiter) ++path_segment; + + const char_t* path_segment_end = path_segment; + + while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end; + + if (path_segment == path_segment_end) return found; + + const char_t* next_segment = path_segment_end; + + while (*next_segment == delimiter) ++next_segment; + + if (*path_segment == '.' && path_segment + 1 == path_segment_end) + return found.first_element_by_path(next_segment, delimiter); + else if (*path_segment == '.' && *(path_segment+1) == '.' && path_segment + 2 == path_segment_end) + return found.parent().first_element_by_path(next_segment, delimiter); + else + { + for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling) + { + if (j->name && impl::strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) + { + xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); + + if (subsearch) return subsearch; + } + } + + return xml_node(); + } + } + + PUGI__FN bool xml_node::traverse(xml_tree_walker& walker) + { + walker._depth = -1; + + xml_node arg_begin = *this; + if (!walker.begin(arg_begin)) return false; + + xml_node cur = first_child(); + + if (cur) + { + ++walker._depth; + + do + { + xml_node arg_for_each = cur; + if (!walker.for_each(arg_for_each)) + return false; + + if (cur.first_child()) + { + ++walker._depth; + cur = cur.first_child(); + } + else if (cur.next_sibling()) + cur = cur.next_sibling(); + else + { + // Borland C++ workaround + while (!cur.next_sibling() && cur != *this && !cur.parent().empty()) + { + --walker._depth; + cur = cur.parent(); + } + + if (cur != *this) + cur = cur.next_sibling(); + } + } + while (cur && cur != *this); + } + + assert(walker._depth == -1); + + xml_node arg_end = *this; + return walker.end(arg_end); + } + + PUGI__FN size_t xml_node::hash_value() const + { + return static_cast(reinterpret_cast(_root) / sizeof(xml_node_struct)); + } + + PUGI__FN xml_node_struct* xml_node::internal_object() const + { + return _root; + } + + PUGI__FN void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + { + if (!_root) return; + + impl::xml_buffered_writer buffered_writer(writer, encoding); + + impl::node_output(buffered_writer, _root, indent, flags, depth); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + { + xml_writer_stream writer(stream); + + print(writer, indent, flags, encoding, depth); + } + + PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const + { + xml_writer_stream writer(stream); + + print(writer, indent, flags, encoding_wchar, depth); + } +#endif + + PUGI__FN ptrdiff_t xml_node::offset_debug() const + { + if (!_root) return -1; + + impl::xml_document_struct& doc = impl::get_document(_root); + + // we can determine the offset reliably only if there is exactly once parse buffer + if (!doc.buffer || doc.extra_buffers) return -1; + + switch (type()) + { + case node_document: + return 0; + + case node_element: + case node_declaration: + case node_pi: + return _root->name && (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0 ? _root->name - doc.buffer : -1; + + case node_pcdata: + case node_cdata: + case node_comment: + case node_doctype: + return _root->value && (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0 ? _root->value - doc.buffer : -1; + + default: + return -1; + } + } + +#ifdef __BORLANDC__ + PUGI__FN bool operator&&(const xml_node& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + PUGI__FN bool operator||(const xml_node& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + PUGI__FN xml_text::xml_text(xml_node_struct* root): _root(root) + { + } + + PUGI__FN xml_node_struct* xml_text::_data() const + { + if (!_root || impl::is_text_node(_root)) return _root; + + for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling) + if (impl::is_text_node(node)) + return node; + + return 0; + } + + PUGI__FN xml_node_struct* xml_text::_data_new() + { + xml_node_struct* d = _data(); + if (d) return d; + + return xml_node(_root).append_child(node_pcdata).internal_object(); + } + + PUGI__FN xml_text::xml_text(): _root(0) + { + } + + PUGI__FN static void unspecified_bool_xml_text(xml_text***) + { + } + + PUGI__FN xml_text::operator xml_text::unspecified_bool_type() const + { + return _data() ? unspecified_bool_xml_text : 0; + } + + PUGI__FN bool xml_text::operator!() const + { + return !_data(); + } + + PUGI__FN bool xml_text::empty() const + { + return _data() == 0; + } + + PUGI__FN const char_t* xml_text::get() const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? d->value : PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* xml_text::as_string(const char_t* def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? d->value : def; + } + + PUGI__FN int xml_text::as_int(int def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_int(d ? d->value : 0, def); + } + + PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_uint(d ? d->value : 0, def); + } + + PUGI__FN double xml_text::as_double(double def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_double(d ? d->value : 0, def); + } + + PUGI__FN float xml_text::as_float(float def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_float(d ? d->value : 0, def); + } + + PUGI__FN bool xml_text::as_bool(bool def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_bool(d ? d->value : 0, def); + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long xml_text::as_llong(long long def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_llong(d ? d->value : 0, def); + } + + PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const + { + xml_node_struct* d = _data(); + + return impl::get_value_ullong(d ? d->value : 0, def); + } +#endif + + PUGI__FN bool xml_text::set(const char_t* rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + + PUGI__FN bool xml_text::set(int rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + + PUGI__FN bool xml_text::set(unsigned int rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + + PUGI__FN bool xml_text::set(float rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + + PUGI__FN bool xml_text::set(double rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + + PUGI__FN bool xml_text::set(bool rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN bool xml_text::set(long long rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + + PUGI__FN bool xml_text::set(unsigned long long rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } +#endif + + PUGI__FN xml_text& xml_text::operator=(const char_t* rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(int rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(unsigned int rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(double rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(float rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(bool rhs) + { + set(rhs); + return *this; + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN xml_text& xml_text::operator=(long long rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(unsigned long long rhs) + { + set(rhs); + return *this; + } +#endif + + PUGI__FN xml_node xml_text::data() const + { + return xml_node(_data()); + } + +#ifdef __BORLANDC__ + PUGI__FN bool operator&&(const xml_text& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + PUGI__FN bool operator||(const xml_text& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + PUGI__FN xml_node_iterator::xml_node_iterator() + { + } + + PUGI__FN xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent()) + { + } + + PUGI__FN xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) + { + } + + PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const + { + return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; + } + + PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const + { + return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; + } + + PUGI__FN xml_node& xml_node_iterator::operator*() const + { + assert(_wrap._root); + return _wrap; + } + + PUGI__FN xml_node* xml_node_iterator::operator->() const + { + assert(_wrap._root); + return const_cast(&_wrap); // BCC32 workaround + } + + PUGI__FN const xml_node_iterator& xml_node_iterator::operator++() + { + assert(_wrap._root); + _wrap._root = _wrap._root->next_sibling; + return *this; + } + + PUGI__FN xml_node_iterator xml_node_iterator::operator++(int) + { + xml_node_iterator temp = *this; + ++*this; + return temp; + } + + PUGI__FN const xml_node_iterator& xml_node_iterator::operator--() + { + _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child(); + return *this; + } + + PUGI__FN xml_node_iterator xml_node_iterator::operator--(int) + { + xml_node_iterator temp = *this; + --*this; + return temp; + } + + PUGI__FN xml_attribute_iterator::xml_attribute_iterator() + { + } + + PUGI__FN xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent) + { + } + + PUGI__FN xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) + { + } + + PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const + { + return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root; + } + + PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const + { + return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root; + } + + PUGI__FN xml_attribute& xml_attribute_iterator::operator*() const + { + assert(_wrap._attr); + return _wrap; + } + + PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const + { + assert(_wrap._attr); + return const_cast(&_wrap); // BCC32 workaround + } + + PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator++() + { + assert(_wrap._attr); + _wrap._attr = _wrap._attr->next_attribute; + return *this; + } + + PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator++(int) + { + xml_attribute_iterator temp = *this; + ++*this; + return temp; + } + + PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator--() + { + _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute(); + return *this; + } + + PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator--(int) + { + xml_attribute_iterator temp = *this; + --*this; + return temp; + } + + PUGI__FN xml_named_node_iterator::xml_named_node_iterator(): _name(0) + { + } + + PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _wrap(node), _parent(node.parent()), _name(name) + { + } + + PUGI__FN xml_named_node_iterator::xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name): _wrap(ref), _parent(parent), _name(name) + { + } + + PUGI__FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const + { + return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; + } + + PUGI__FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const + { + return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; + } + + PUGI__FN xml_node& xml_named_node_iterator::operator*() const + { + assert(_wrap._root); + return _wrap; + } + + PUGI__FN xml_node* xml_named_node_iterator::operator->() const + { + assert(_wrap._root); + return const_cast(&_wrap); // BCC32 workaround + } + + PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator++() + { + assert(_wrap._root); + _wrap = _wrap.next_sibling(_name); + return *this; + } + + PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator++(int) + { + xml_named_node_iterator temp = *this; + ++*this; + return temp; + } + + PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator--() + { + if (_wrap._root) + _wrap = _wrap.previous_sibling(_name); + else + { + _wrap = _parent.last_child(); + + if (!impl::strequal(_wrap.name(), _name)) + _wrap = _wrap.previous_sibling(_name); + } + + return *this; + } + + PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator--(int) + { + xml_named_node_iterator temp = *this; + --*this; + return temp; + } + + PUGI__FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) + { + } + + PUGI__FN xml_parse_result::operator bool() const + { + return status == status_ok; + } + + PUGI__FN const char* xml_parse_result::description() const + { + switch (status) + { + case status_ok: return "No error"; + + case status_file_not_found: return "File was not found"; + case status_io_error: return "Error reading from file/stream"; + case status_out_of_memory: return "Could not allocate memory"; + case status_internal_error: return "Internal error occurred"; + + case status_unrecognized_tag: return "Could not determine tag type"; + + case status_bad_pi: return "Error parsing document declaration/processing instruction"; + case status_bad_comment: return "Error parsing comment"; + case status_bad_cdata: return "Error parsing CDATA section"; + case status_bad_doctype: return "Error parsing document type declaration"; + case status_bad_pcdata: return "Error parsing PCDATA section"; + case status_bad_start_element: return "Error parsing start element tag"; + case status_bad_attribute: return "Error parsing element attribute"; + case status_bad_end_element: return "Error parsing end element tag"; + case status_end_element_mismatch: return "Start-end tags mismatch"; + + case status_append_invalid_root: return "Unable to append nodes: root is not an element or document"; + + case status_no_document_element: return "No document element found"; + + default: return "Unknown error"; + } + } + + PUGI__FN xml_document::xml_document(): _buffer(0) + { + create(); + } + + PUGI__FN xml_document::~xml_document() + { + destroy(); + } + + PUGI__FN void xml_document::reset() + { + destroy(); + create(); + } + + PUGI__FN void xml_document::reset(const xml_document& proto) + { + reset(); + + for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling()) + append_copy(cur); + } + + PUGI__FN void xml_document::create() + { + assert(!_root); + + // initialize sentinel page + PUGI__STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + impl::xml_memory_page_alignment - sizeof(void*) <= sizeof(_memory)); + + // align upwards to page boundary + void* page_memory = reinterpret_cast((reinterpret_cast(_memory) + (impl::xml_memory_page_alignment - 1)) & ~(impl::xml_memory_page_alignment - 1)); + + // prepare page structure + impl::xml_memory_page* page = impl::xml_memory_page::construct(page_memory); + assert(page); + + page->busy_size = impl::xml_memory_page_size; + + // allocate new root + _root = new (reinterpret_cast(page) + sizeof(impl::xml_memory_page)) impl::xml_document_struct(page); + _root->prev_sibling_c = _root; + + // setup sentinel page + page->allocator = static_cast(_root); + + // verify the document allocation + assert(reinterpret_cast(_root) + sizeof(impl::xml_document_struct) <= _memory + sizeof(_memory)); + } + + PUGI__FN void xml_document::destroy() + { + assert(_root); + + // destroy static storage + if (_buffer) + { + impl::xml_memory::deallocate(_buffer); + _buffer = 0; + } + + // destroy extra buffers (note: no need to destroy linked list nodes, they're allocated using document allocator) + for (impl::xml_extra_buffer* extra = static_cast(_root)->extra_buffers; extra; extra = extra->next) + { + if (extra->buffer) impl::xml_memory::deallocate(extra->buffer); + } + + // destroy dynamic storage, leave sentinel page (it's in static memory) + impl::xml_memory_page* root_page = reinterpret_cast(_root->header & impl::xml_memory_page_pointer_mask); + assert(root_page && !root_page->prev); + assert(reinterpret_cast(root_page) >= _memory && reinterpret_cast(root_page) < _memory + sizeof(_memory)); + + for (impl::xml_memory_page* page = root_page->next; page; ) + { + impl::xml_memory_page* next = page->next; + + impl::xml_allocator::deallocate_page(page); + + page = next; + } + + _root = 0; + } + +#ifndef PUGIXML_NO_STL + PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) + { + reset(); + + return impl::load_stream_impl(*this, stream, options, encoding); + } + + PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) + { + reset(); + + return impl::load_stream_impl(*this, stream, options, encoding_wchar); + } +#endif + + PUGI__FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options) + { + // Force native encoding (skip autodetection) + #ifdef PUGIXML_WCHAR_MODE + xml_encoding encoding = encoding_wchar; + #else + xml_encoding encoding = encoding_utf8; + #endif + + return load_buffer(contents, impl::strlength(contents) * sizeof(char_t), options, encoding); + } + + PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) + { + return load_string(contents, options); + } + + PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) + { + reset(); + + FILE* file = fopen(path_, "rb"); + + return impl::load_file_impl(*this, file, options, encoding); + } + + PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding) + { + reset(); + + FILE* file = impl::open_file_wide(path_, L"rb"); + + return impl::load_file_impl(*this, file, options, encoding); + } + + PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + reset(); + + return impl::load_buffer_impl(static_cast(_root), _root, const_cast(contents), size, options, encoding, false, false, &_buffer); + } + + PUGI__FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + reset(); + + return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, false, &_buffer); + } + + PUGI__FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + reset(); + + return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, true, &_buffer); + } + + PUGI__FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + impl::xml_buffered_writer buffered_writer(writer, encoding); + + if ((flags & format_write_bom) && encoding != encoding_latin1) + { + // BOM always represents the codepoint U+FEFF, so just write it in native encoding + #ifdef PUGIXML_WCHAR_MODE + unsigned int bom = 0xfeff; + buffered_writer.write(static_cast(bom)); + #else + buffered_writer.write('\xef', '\xbb', '\xbf'); + #endif + } + + if (!(flags & format_no_declaration) && !impl::has_declaration(_root)) + { + buffered_writer.write_string(PUGIXML_TEXT("'); + if (!(flags & format_raw)) buffered_writer.write('\n'); + } + + impl::node_output(buffered_writer, _root, indent, flags, 0); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + xml_writer_stream writer(stream); + + save(writer, indent, flags, encoding); + } + + PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const + { + xml_writer_stream writer(stream); + + save(writer, indent, flags, encoding_wchar); + } +#endif + + PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + FILE* file = fopen(path_, (flags & format_save_file_text) ? "w" : "wb"); + return impl::save_file_impl(*this, file, indent, flags, encoding); + } + + PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + FILE* file = impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"); + return impl::save_file_impl(*this, file, indent, flags, encoding); + } + + PUGI__FN xml_node xml_document::document_element() const + { + assert(_root); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (PUGI__NODETYPE(i) == node_element) + return xml_node(i); + + return xml_node(); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str) + { + assert(str); + + return impl::as_utf8_impl(str, impl::strlength_wide(str)); + } + + PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string& str) + { + return impl::as_utf8_impl(str.c_str(), str.size()); + } + + PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const char* str) + { + assert(str); + + return impl::as_wide_impl(str, strlen(str)); + } + + PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const std::string& str) + { + return impl::as_wide_impl(str.c_str(), str.size()); + } +#endif + + PUGI__FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate) + { + impl::xml_memory::allocate = allocate; + impl::xml_memory::deallocate = deallocate; + } + + PUGI__FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function() + { + return impl::xml_memory::allocate; + } + + PUGI__FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function() + { + return impl::xml_memory::deallocate; + } +} + +#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) +namespace std +{ + // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) + PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } +} +#endif + +#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) +namespace std +{ + // Workarounds for (non-standard) iterator category detection + PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } +} +#endif + +#ifndef PUGIXML_NO_XPATH +// STL replacements +PUGI__NS_BEGIN + struct equal_to + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs == rhs; + } + }; + + struct not_equal_to + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs != rhs; + } + }; + + struct less + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs < rhs; + } + }; + + struct less_equal + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs <= rhs; + } + }; + + template void swap(T& lhs, T& rhs) + { + T temp = lhs; + lhs = rhs; + rhs = temp; + } + + template I min_element(I begin, I end, const Pred& pred) + { + I result = begin; + + for (I it = begin + 1; it != end; ++it) + if (pred(*it, *result)) + result = it; + + return result; + } + + template void reverse(I begin, I end) + { + while (end - begin > 1) swap(*begin++, *--end); + } + + template I unique(I begin, I end) + { + // fast skip head + while (end - begin > 1 && *begin != *(begin + 1)) begin++; + + if (begin == end) return begin; + + // last written element + I write = begin++; + + // merge unique elements + while (begin != end) + { + if (*begin != *write) + *++write = *begin++; + else + begin++; + } + + // past-the-end (write points to live element) + return write + 1; + } + + template void copy_backwards(I begin, I end, I target) + { + while (begin != end) *--target = *--end; + } + + template void insertion_sort(I begin, I end, const Pred& pred, T*) + { + assert(begin != end); + + for (I it = begin + 1; it != end; ++it) + { + T val = *it; + + if (pred(val, *begin)) + { + // move to front + copy_backwards(begin, it, it + 1); + *begin = val; + } + else + { + I hole = it; + + // move hole backwards + while (pred(val, *(hole - 1))) + { + *hole = *(hole - 1); + hole--; + } + + // fill hole with element + *hole = val; + } + } + } + + // std variant for elements with == + template void partition(I begin, I middle, I end, const Pred& pred, I* out_eqbeg, I* out_eqend) + { + I eqbeg = middle, eqend = middle + 1; + + // expand equal range + while (eqbeg != begin && *(eqbeg - 1) == *eqbeg) --eqbeg; + while (eqend != end && *eqend == *eqbeg) ++eqend; + + // process outer elements + I ltend = eqbeg, gtbeg = eqend; + + for (;;) + { + // find the element from the right side that belongs to the left one + for (; gtbeg != end; ++gtbeg) + if (!pred(*eqbeg, *gtbeg)) + { + if (*gtbeg == *eqbeg) swap(*gtbeg, *eqend++); + else break; + } + + // find the element from the left side that belongs to the right one + for (; ltend != begin; --ltend) + if (!pred(*(ltend - 1), *eqbeg)) + { + if (*eqbeg == *(ltend - 1)) swap(*(ltend - 1), *--eqbeg); + else break; + } + + // scanned all elements + if (gtbeg == end && ltend == begin) + { + *out_eqbeg = eqbeg; + *out_eqend = eqend; + return; + } + + // make room for elements by moving equal area + if (gtbeg == end) + { + if (--ltend != --eqbeg) swap(*ltend, *eqbeg); + swap(*eqbeg, *--eqend); + } + else if (ltend == begin) + { + if (eqend != gtbeg) swap(*eqbeg, *eqend); + ++eqend; + swap(*gtbeg++, *eqbeg++); + } + else swap(*gtbeg++, *--ltend); + } + } + + template void median3(I first, I middle, I last, const Pred& pred) + { + if (pred(*middle, *first)) swap(*middle, *first); + if (pred(*last, *middle)) swap(*last, *middle); + if (pred(*middle, *first)) swap(*middle, *first); + } + + template void median(I first, I middle, I last, const Pred& pred) + { + if (last - first <= 40) + { + // median of three for small chunks + median3(first, middle, last, pred); + } + else + { + // median of nine + size_t step = (last - first + 1) / 8; + + median3(first, first + step, first + 2 * step, pred); + median3(middle - step, middle, middle + step, pred); + median3(last - 2 * step, last - step, last, pred); + median3(first + step, middle, last - step, pred); + } + } + + template void sort(I begin, I end, const Pred& pred) + { + // sort large chunks + while (end - begin > 32) + { + // find median element + I middle = begin + (end - begin) / 2; + median(begin, middle, end - 1, pred); + + // partition in three chunks (< = >) + I eqbeg, eqend; + partition(begin, middle, end, pred, &eqbeg, &eqend); + + // loop on larger half + if (eqbeg - begin > end - eqend) + { + sort(eqend, end, pred); + end = eqbeg; + } + else + { + sort(begin, eqbeg, pred); + begin = eqend; + } + } + + // insertion sort small chunk + if (begin != end) insertion_sort(begin, end, pred, &*begin); + } +PUGI__NS_END + +// Allocator used for AST and evaluation stacks +PUGI__NS_BEGIN + struct xpath_memory_block + { + xpath_memory_block* next; + size_t capacity; + + char data[ + #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE + PUGIXML_MEMORY_XPATH_PAGE_SIZE + #else + 4096 + #endif + ]; + }; + + class xpath_allocator + { + xpath_memory_block* _root; + size_t _root_size; + + public: + #ifdef PUGIXML_NO_EXCEPTIONS + jmp_buf* error_handler; + #endif + + xpath_allocator(xpath_memory_block* root, size_t root_size = 0): _root(root), _root_size(root_size) + { + #ifdef PUGIXML_NO_EXCEPTIONS + error_handler = 0; + #endif + } + + void* allocate_nothrow(size_t size) + { + // align size so that we're able to store pointers in subsequent blocks + size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); + + if (_root_size + size <= _root->capacity) + { + void* buf = _root->data + _root_size; + _root_size += size; + return buf; + } + else + { + // make sure we have at least 1/4th of the page free after allocation to satisfy subsequent allocation requests + size_t block_capacity_base = sizeof(_root->data); + size_t block_capacity_req = size + block_capacity_base / 4; + size_t block_capacity = (block_capacity_base > block_capacity_req) ? block_capacity_base : block_capacity_req; + + size_t block_size = block_capacity + offsetof(xpath_memory_block, data); + + xpath_memory_block* block = static_cast(xml_memory::allocate(block_size)); + if (!block) return 0; + + block->next = _root; + block->capacity = block_capacity; + + _root = block; + _root_size = size; + + return block->data; + } + } + + void* allocate(size_t size) + { + void* result = allocate_nothrow(size); + + if (!result) + { + #ifdef PUGIXML_NO_EXCEPTIONS + assert(error_handler); + longjmp(*error_handler, 1); + #else + throw std::bad_alloc(); + #endif + } + + return result; + } + + void* reallocate(void* ptr, size_t old_size, size_t new_size) + { + // align size so that we're able to store pointers in subsequent blocks + old_size = (old_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); + new_size = (new_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); + + // we can only reallocate the last object + assert(ptr == 0 || static_cast(ptr) + old_size == _root->data + _root_size); + + // adjust root size so that we have not allocated the object at all + bool only_object = (_root_size == old_size); + + if (ptr) _root_size -= old_size; + + // allocate a new version (this will obviously reuse the memory if possible) + void* result = allocate(new_size); + assert(result); + + // we have a new block + if (result != ptr && ptr) + { + // copy old data + assert(new_size >= old_size); + memcpy(result, ptr, old_size); + + // free the previous page if it had no other objects + if (only_object) + { + assert(_root->data == result); + assert(_root->next); + + xpath_memory_block* next = _root->next->next; + + if (next) + { + // deallocate the whole page, unless it was the first one + xml_memory::deallocate(_root->next); + _root->next = next; + } + } + } + + return result; + } + + void revert(const xpath_allocator& state) + { + // free all new pages + xpath_memory_block* cur = _root; + + while (cur != state._root) + { + xpath_memory_block* next = cur->next; + + xml_memory::deallocate(cur); + + cur = next; + } + + // restore state + _root = state._root; + _root_size = state._root_size; + } + + void release() + { + xpath_memory_block* cur = _root; + assert(cur); + + while (cur->next) + { + xpath_memory_block* next = cur->next; + + xml_memory::deallocate(cur); + + cur = next; + } + } + }; + + struct xpath_allocator_capture + { + xpath_allocator_capture(xpath_allocator* alloc): _target(alloc), _state(*alloc) + { + } + + ~xpath_allocator_capture() + { + _target->revert(_state); + } + + xpath_allocator* _target; + xpath_allocator _state; + }; + + struct xpath_stack + { + xpath_allocator* result; + xpath_allocator* temp; + }; + + struct xpath_stack_data + { + xpath_memory_block blocks[2]; + xpath_allocator result; + xpath_allocator temp; + xpath_stack stack; + + #ifdef PUGIXML_NO_EXCEPTIONS + jmp_buf error_handler; + #endif + + xpath_stack_data(): result(blocks + 0), temp(blocks + 1) + { + blocks[0].next = blocks[1].next = 0; + blocks[0].capacity = blocks[1].capacity = sizeof(blocks[0].data); + + stack.result = &result; + stack.temp = &temp; + + #ifdef PUGIXML_NO_EXCEPTIONS + result.error_handler = temp.error_handler = &error_handler; + #endif + } + + ~xpath_stack_data() + { + result.release(); + temp.release(); + } + }; +PUGI__NS_END + +// String class +PUGI__NS_BEGIN + class xpath_string + { + const char_t* _buffer; + bool _uses_heap; + size_t _length_heap; + + static char_t* duplicate_string(const char_t* string, size_t length, xpath_allocator* alloc) + { + char_t* result = static_cast(alloc->allocate((length + 1) * sizeof(char_t))); + assert(result); + + memcpy(result, string, length * sizeof(char_t)); + result[length] = 0; + + return result; + } + + xpath_string(const char_t* buffer, bool uses_heap_, size_t length_heap): _buffer(buffer), _uses_heap(uses_heap_), _length_heap(length_heap) + { + } + + public: + static xpath_string from_const(const char_t* str) + { + return xpath_string(str, false, 0); + } + + static xpath_string from_heap_preallocated(const char_t* begin, const char_t* end) + { + assert(begin <= end && *end == 0); + + return xpath_string(begin, true, static_cast(end - begin)); + } + + static xpath_string from_heap(const char_t* begin, const char_t* end, xpath_allocator* alloc) + { + assert(begin <= end); + + size_t length = static_cast(end - begin); + + return length == 0 ? xpath_string() : xpath_string(duplicate_string(begin, length, alloc), true, length); + } + + xpath_string(): _buffer(PUGIXML_TEXT("")), _uses_heap(false), _length_heap(0) + { + } + + void append(const xpath_string& o, xpath_allocator* alloc) + { + // skip empty sources + if (!*o._buffer) return; + + // fast append for constant empty target and constant source + if (!*_buffer && !_uses_heap && !o._uses_heap) + { + _buffer = o._buffer; + } + else + { + // need to make heap copy + size_t target_length = length(); + size_t source_length = o.length(); + size_t result_length = target_length + source_length; + + // allocate new buffer + char_t* result = static_cast(alloc->reallocate(_uses_heap ? const_cast(_buffer) : 0, (target_length + 1) * sizeof(char_t), (result_length + 1) * sizeof(char_t))); + assert(result); + + // append first string to the new buffer in case there was no reallocation + if (!_uses_heap) memcpy(result, _buffer, target_length * sizeof(char_t)); + + // append second string to the new buffer + memcpy(result + target_length, o._buffer, source_length * sizeof(char_t)); + result[result_length] = 0; + + // finalize + _buffer = result; + _uses_heap = true; + _length_heap = result_length; + } + } + + const char_t* c_str() const + { + return _buffer; + } + + size_t length() const + { + return _uses_heap ? _length_heap : strlength(_buffer); + } + + char_t* data(xpath_allocator* alloc) + { + // make private heap copy + if (!_uses_heap) + { + size_t length_ = strlength(_buffer); + + _buffer = duplicate_string(_buffer, length_, alloc); + _uses_heap = true; + _length_heap = length_; + } + + return const_cast(_buffer); + } + + bool empty() const + { + return *_buffer == 0; + } + + bool operator==(const xpath_string& o) const + { + return strequal(_buffer, o._buffer); + } + + bool operator!=(const xpath_string& o) const + { + return !strequal(_buffer, o._buffer); + } + + bool uses_heap() const + { + return _uses_heap; + } + }; +PUGI__NS_END + +PUGI__NS_BEGIN + PUGI__FN bool starts_with(const char_t* string, const char_t* pattern) + { + while (*pattern && *string == *pattern) + { + string++; + pattern++; + } + + return *pattern == 0; + } + + PUGI__FN const char_t* find_char(const char_t* s, char_t c) + { + #ifdef PUGIXML_WCHAR_MODE + return wcschr(s, c); + #else + return strchr(s, c); + #endif + } + + PUGI__FN const char_t* find_substring(const char_t* s, const char_t* p) + { + #ifdef PUGIXML_WCHAR_MODE + // MSVC6 wcsstr bug workaround (if s is empty it always returns 0) + return (*p == 0) ? s : wcsstr(s, p); + #else + return strstr(s, p); + #endif + } + + // Converts symbol to lower case, if it is an ASCII one + PUGI__FN char_t tolower_ascii(char_t ch) + { + return static_cast(ch - 'A') < 26 ? static_cast(ch | ' ') : ch; + } + + PUGI__FN xpath_string string_value(const xpath_node& na, xpath_allocator* alloc) + { + if (na.attribute()) + return xpath_string::from_const(na.attribute().value()); + else + { + xml_node n = na.node(); + + switch (n.type()) + { + case node_pcdata: + case node_cdata: + case node_comment: + case node_pi: + return xpath_string::from_const(n.value()); + + case node_document: + case node_element: + { + xpath_string result; + + xml_node cur = n.first_child(); + + while (cur && cur != n) + { + if (cur.type() == node_pcdata || cur.type() == node_cdata) + result.append(xpath_string::from_const(cur.value()), alloc); + + if (cur.first_child()) + cur = cur.first_child(); + else if (cur.next_sibling()) + cur = cur.next_sibling(); + else + { + while (!cur.next_sibling() && cur != n) + cur = cur.parent(); + + if (cur != n) cur = cur.next_sibling(); + } + } + + return result; + } + + default: + return xpath_string(); + } + } + } + + PUGI__FN bool node_is_before_sibling(xml_node_struct* ln, xml_node_struct* rn) + { + assert(ln->parent == rn->parent); + + // there is no common ancestor (the shared parent is null), nodes are from different documents + if (!ln->parent) return ln < rn; + + // determine sibling order + xml_node_struct* ls = ln; + xml_node_struct* rs = rn; + + while (ls && rs) + { + if (ls == rn) return true; + if (rs == ln) return false; + + ls = ls->next_sibling; + rs = rs->next_sibling; + } + + // if rn sibling chain ended ln must be before rn + return !rs; + } + + PUGI__FN bool node_is_before(xml_node_struct* ln, xml_node_struct* rn) + { + // find common ancestor at the same depth, if any + xml_node_struct* lp = ln; + xml_node_struct* rp = rn; + + while (lp && rp && lp->parent != rp->parent) + { + lp = lp->parent; + rp = rp->parent; + } + + // parents are the same! + if (lp && rp) return node_is_before_sibling(lp, rp); + + // nodes are at different depths, need to normalize heights + bool left_higher = !lp; + + while (lp) + { + lp = lp->parent; + ln = ln->parent; + } + + while (rp) + { + rp = rp->parent; + rn = rn->parent; + } + + // one node is the ancestor of the other + if (ln == rn) return left_higher; + + // find common ancestor... again + while (ln->parent != rn->parent) + { + ln = ln->parent; + rn = rn->parent; + } + + return node_is_before_sibling(ln, rn); + } + + PUGI__FN bool node_is_ancestor(xml_node_struct* parent, xml_node_struct* node) + { + while (node && node != parent) node = node->parent; + + return parent && node == parent; + } + + PUGI__FN const void* document_buffer_order(const xpath_node& xnode) + { + xml_node_struct* node = xnode.node().internal_object(); + + if (node) + { + if ((get_document(node).header & xml_memory_page_contents_shared_mask) == 0) + { + if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return node->name; + if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return node->value; + } + + return 0; + } + + xml_attribute_struct* attr = xnode.attribute().internal_object(); + + if (attr) + { + if ((get_document(attr).header & xml_memory_page_contents_shared_mask) == 0) + { + if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return attr->name; + if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return attr->value; + } + + return 0; + } + + return 0; + } + + struct document_order_comparator + { + bool operator()(const xpath_node& lhs, const xpath_node& rhs) const + { + // optimized document order based check + const void* lo = document_buffer_order(lhs); + const void* ro = document_buffer_order(rhs); + + if (lo && ro) return lo < ro; + + // slow comparison + xml_node ln = lhs.node(), rn = rhs.node(); + + // compare attributes + if (lhs.attribute() && rhs.attribute()) + { + // shared parent + if (lhs.parent() == rhs.parent()) + { + // determine sibling order + for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute()) + if (a == rhs.attribute()) + return true; + + return false; + } + + // compare attribute parents + ln = lhs.parent(); + rn = rhs.parent(); + } + else if (lhs.attribute()) + { + // attributes go after the parent element + if (lhs.parent() == rhs.node()) return false; + + ln = lhs.parent(); + } + else if (rhs.attribute()) + { + // attributes go after the parent element + if (rhs.parent() == lhs.node()) return true; + + rn = rhs.parent(); + } + + if (ln == rn) return false; + + if (!ln || !rn) return ln < rn; + + return node_is_before(ln.internal_object(), rn.internal_object()); + } + }; + + struct duplicate_comparator + { + bool operator()(const xpath_node& lhs, const xpath_node& rhs) const + { + if (lhs.attribute()) return rhs.attribute() ? lhs.attribute() < rhs.attribute() : true; + else return rhs.attribute() ? false : lhs.node() < rhs.node(); + } + }; + + PUGI__FN double gen_nan() + { + #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24)) + union { float f; uint32_t i; } u[sizeof(float) == sizeof(uint32_t) ? 1 : -1]; + u[0].i = 0x7fc00000; + return u[0].f; + #else + // fallback + const volatile double zero = 0.0; + return zero / zero; + #endif + } + + PUGI__FN bool is_nan(double value) + { + #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) + return !!_isnan(value); + #elif defined(fpclassify) && defined(FP_NAN) + return fpclassify(value) == FP_NAN; + #else + // fallback + const volatile double v = value; + return v != v; + #endif + } + + PUGI__FN const char_t* convert_number_to_string_special(double value) + { + #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) + if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0; + if (_isnan(value)) return PUGIXML_TEXT("NaN"); + return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); + #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) + switch (fpclassify(value)) + { + case FP_NAN: + return PUGIXML_TEXT("NaN"); + + case FP_INFINITE: + return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); + + case FP_ZERO: + return PUGIXML_TEXT("0"); + + default: + return 0; + } + #else + // fallback + const volatile double v = value; + + if (v == 0) return PUGIXML_TEXT("0"); + if (v != v) return PUGIXML_TEXT("NaN"); + if (v * 2 == v) return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); + return 0; + #endif + } + + PUGI__FN bool convert_number_to_boolean(double value) + { + return (value != 0 && !is_nan(value)); + } + + PUGI__FN void truncate_zeros(char* begin, char* end) + { + while (begin != end && end[-1] == '0') end--; + + *end = 0; + } + + // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) + PUGI__FN void convert_number_to_mantissa_exponent(double value, char* buffer, size_t buffer_size, char** out_mantissa, int* out_exponent) + { + // get base values + int sign, exponent; + _ecvt_s(buffer, buffer_size, value, DBL_DIG + 1, &exponent, &sign); + + // truncate redundant zeros + truncate_zeros(buffer, buffer + strlen(buffer)); + + // fill results + *out_mantissa = buffer; + *out_exponent = exponent; + } +#else + PUGI__FN void convert_number_to_mantissa_exponent(double value, char* buffer, size_t buffer_size, char** out_mantissa, int* out_exponent) + { + // get a scientific notation value with IEEE DBL_DIG decimals + sprintf(buffer, "%.*e", DBL_DIG, value); + assert(strlen(buffer) < buffer_size); + (void)!buffer_size; + + // get the exponent (possibly negative) + char* exponent_string = strchr(buffer, 'e'); + assert(exponent_string); + + int exponent = atoi(exponent_string + 1); + + // extract mantissa string: skip sign + char* mantissa = buffer[0] == '-' ? buffer + 1 : buffer; + assert(mantissa[0] != '0' && mantissa[1] == '.'); + + // divide mantissa by 10 to eliminate integer part + mantissa[1] = mantissa[0]; + mantissa++; + exponent++; + + // remove extra mantissa digits and zero-terminate mantissa + truncate_zeros(mantissa, exponent_string); + + // fill results + *out_mantissa = mantissa; + *out_exponent = exponent; + } +#endif + + PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator* alloc) + { + // try special number conversion + const char_t* special = convert_number_to_string_special(value); + if (special) return xpath_string::from_const(special); + + // get mantissa + exponent form + char mantissa_buffer[32]; + + char* mantissa; + int exponent; + convert_number_to_mantissa_exponent(value, mantissa_buffer, sizeof(mantissa_buffer), &mantissa, &exponent); + + // allocate a buffer of suitable length for the number + size_t result_size = strlen(mantissa_buffer) + (exponent > 0 ? exponent : -exponent) + 4; + char_t* result = static_cast(alloc->allocate(sizeof(char_t) * result_size)); + assert(result); + + // make the number! + char_t* s = result; + + // sign + if (value < 0) *s++ = '-'; + + // integer part + if (exponent <= 0) + { + *s++ = '0'; + } + else + { + while (exponent > 0) + { + assert(*mantissa == 0 || static_cast(static_cast(*mantissa) - '0') <= 9); + *s++ = *mantissa ? *mantissa++ : '0'; + exponent--; + } + } + + // fractional part + if (*mantissa) + { + // decimal point + *s++ = '.'; + + // extra zeroes from negative exponent + while (exponent < 0) + { + *s++ = '0'; + exponent++; + } + + // extra mantissa digits + while (*mantissa) + { + assert(static_cast(*mantissa - '0') <= 9); + *s++ = *mantissa++; + } + } + + // zero-terminate + assert(s < result + result_size); + *s = 0; + + return xpath_string::from_heap_preallocated(result, s); + } + + PUGI__FN bool check_string_to_number_format(const char_t* string) + { + // parse leading whitespace + while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; + + // parse sign + if (*string == '-') ++string; + + if (!*string) return false; + + // if there is no integer part, there should be a decimal part with at least one digit + if (!PUGI__IS_CHARTYPEX(string[0], ctx_digit) && (string[0] != '.' || !PUGI__IS_CHARTYPEX(string[1], ctx_digit))) return false; + + // parse integer part + while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; + + // parse decimal part + if (*string == '.') + { + ++string; + + while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; + } + + // parse trailing whitespace + while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; + + return *string == 0; + } + + PUGI__FN double convert_string_to_number(const char_t* string) + { + // check string format + if (!check_string_to_number_format(string)) return gen_nan(); + + // parse string + #ifdef PUGIXML_WCHAR_MODE + return wcstod(string, 0); + #else + return atof(string); + #endif + } + + PUGI__FN bool convert_string_to_number_scratch(char_t (&buffer)[32], const char_t* begin, const char_t* end, double* out_result) + { + size_t length = static_cast(end - begin); + char_t* scratch = buffer; + + if (length >= sizeof(buffer) / sizeof(buffer[0])) + { + // need to make dummy on-heap copy + scratch = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!scratch) return false; + } + + // copy string to zero-terminated buffer and perform conversion + memcpy(scratch, begin, length * sizeof(char_t)); + scratch[length] = 0; + + *out_result = convert_string_to_number(scratch); + + // free dummy buffer + if (scratch != buffer) xml_memory::deallocate(scratch); + + return true; + } + + PUGI__FN double round_nearest(double value) + { + return floor(value + 0.5); + } + + PUGI__FN double round_nearest_nzero(double value) + { + // same as round_nearest, but returns -0 for [-0.5, -0] + // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0) + return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5); + } + + PUGI__FN const char_t* qualified_name(const xpath_node& node) + { + return node.attribute() ? node.attribute().name() : node.node().name(); + } + + PUGI__FN const char_t* local_name(const xpath_node& node) + { + const char_t* name = qualified_name(node); + const char_t* p = find_char(name, ':'); + + return p ? p + 1 : name; + } + + struct namespace_uri_predicate + { + const char_t* prefix; + size_t prefix_length; + + namespace_uri_predicate(const char_t* name) + { + const char_t* pos = find_char(name, ':'); + + prefix = pos ? name : 0; + prefix_length = pos ? static_cast(pos - name) : 0; + } + + bool operator()(xml_attribute a) const + { + const char_t* name = a.name(); + + if (!starts_with(name, PUGIXML_TEXT("xmlns"))) return false; + + return prefix ? name[5] == ':' && strequalrange(name + 6, prefix, prefix_length) : name[5] == 0; + } + }; + + PUGI__FN const char_t* namespace_uri(xml_node node) + { + namespace_uri_predicate pred = node.name(); + + xml_node p = node; + + while (p) + { + xml_attribute a = p.find_attribute(pred); + + if (a) return a.value(); + + p = p.parent(); + } + + return PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* namespace_uri(xml_attribute attr, xml_node parent) + { + namespace_uri_predicate pred = attr.name(); + + // Default namespace does not apply to attributes + if (!pred.prefix) return PUGIXML_TEXT(""); + + xml_node p = parent; + + while (p) + { + xml_attribute a = p.find_attribute(pred); + + if (a) return a.value(); + + p = p.parent(); + } + + return PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* namespace_uri(const xpath_node& node) + { + return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node()); + } + + PUGI__FN void normalize_space(char_t* buffer) + { + char_t* write = buffer; + + for (char_t* it = buffer; *it; ) + { + char_t ch = *it++; + + if (PUGI__IS_CHARTYPE(ch, ct_space)) + { + // replace whitespace sequence with single space + while (PUGI__IS_CHARTYPE(*it, ct_space)) it++; + + // avoid leading spaces + if (write != buffer) *write++ = ' '; + } + else *write++ = ch; + } + + // remove trailing space + if (write != buffer && PUGI__IS_CHARTYPE(write[-1], ct_space)) write--; + + // zero-terminate + *write = 0; + } + + PUGI__FN void translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length) + { + char_t* write = buffer; + + while (*buffer) + { + PUGI__DMC_VOLATILE char_t ch = *buffer++; + + const char_t* pos = find_char(from, ch); + + if (!pos) + *write++ = ch; // do not process + else if (static_cast(pos - from) < to_length) + *write++ = to[pos - from]; // replace + } + + // zero-terminate + *write = 0; + } + + PUGI__FN unsigned char* translate_table_generate(xpath_allocator* alloc, const char_t* from, const char_t* to) + { + unsigned char table[128] = {0}; + + while (*from) + { + unsigned int fc = static_cast(*from); + unsigned int tc = static_cast(*to); + + if (fc >= 128 || tc >= 128) + return 0; + + // code=128 means "skip character" + if (!table[fc]) + table[fc] = static_cast(tc ? tc : 128); + + from++; + if (tc) to++; + } + + for (int i = 0; i < 128; ++i) + if (!table[i]) + table[i] = static_cast(i); + + void* result = alloc->allocate_nothrow(sizeof(table)); + + if (result) + { + memcpy(result, table, sizeof(table)); + } + + return static_cast(result); + } + + PUGI__FN void translate_table(char_t* buffer, const unsigned char* table) + { + char_t* write = buffer; + + while (*buffer) + { + char_t ch = *buffer++; + unsigned int index = static_cast(ch); + + if (index < 128) + { + unsigned char code = table[index]; + + // code=128 means "skip character" (table size is 128 so 128 can be a special value) + // this code skips these characters without extra branches + *write = static_cast(code); + write += 1 - (code >> 7); + } + else + { + *write++ = ch; + } + } + + // zero-terminate + *write = 0; + } + + inline bool is_xpath_attribute(const char_t* name) + { + return !(starts_with(name, PUGIXML_TEXT("xmlns")) && (name[5] == 0 || name[5] == ':')); + } + + struct xpath_variable_boolean: xpath_variable + { + xpath_variable_boolean(): value(false) + { + } + + bool value; + char_t name[1]; + }; + + struct xpath_variable_number: xpath_variable + { + xpath_variable_number(): value(0) + { + } + + double value; + char_t name[1]; + }; + + struct xpath_variable_string: xpath_variable + { + xpath_variable_string(): value(0) + { + } + + ~xpath_variable_string() + { + if (value) xml_memory::deallocate(value); + } + + char_t* value; + char_t name[1]; + }; + + struct xpath_variable_node_set: xpath_variable + { + xpath_node_set value; + char_t name[1]; + }; + + static const xpath_node_set dummy_node_set; + + PUGI__FN unsigned int hash_string(const char_t* str) + { + // Jenkins one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time) + unsigned int result = 0; + + while (*str) + { + result += static_cast(*str++); + result += result << 10; + result ^= result >> 6; + } + + result += result << 3; + result ^= result >> 11; + result += result << 15; + + return result; + } + + template PUGI__FN T* new_xpath_variable(const char_t* name) + { + size_t length = strlength(name); + if (length == 0) return 0; // empty variable names are invalid + + // $$ we can't use offsetof(T, name) because T is non-POD, so we just allocate additional length characters + void* memory = xml_memory::allocate(sizeof(T) + length * sizeof(char_t)); + if (!memory) return 0; + + T* result = new (memory) T(); + + memcpy(result->name, name, (length + 1) * sizeof(char_t)); + + return result; + } + + PUGI__FN xpath_variable* new_xpath_variable(xpath_value_type type, const char_t* name) + { + switch (type) + { + case xpath_type_node_set: + return new_xpath_variable(name); + + case xpath_type_number: + return new_xpath_variable(name); + + case xpath_type_string: + return new_xpath_variable(name); + + case xpath_type_boolean: + return new_xpath_variable(name); + + default: + return 0; + } + } + + template PUGI__FN void delete_xpath_variable(T* var) + { + var->~T(); + xml_memory::deallocate(var); + } + + PUGI__FN void delete_xpath_variable(xpath_value_type type, xpath_variable* var) + { + switch (type) + { + case xpath_type_node_set: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_number: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_string: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_boolean: + delete_xpath_variable(static_cast(var)); + break; + + default: + assert(!"Invalid variable type"); + } + } + + PUGI__FN xpath_variable* get_variable_scratch(char_t (&buffer)[32], xpath_variable_set* set, const char_t* begin, const char_t* end) + { + size_t length = static_cast(end - begin); + char_t* scratch = buffer; + + if (length >= sizeof(buffer) / sizeof(buffer[0])) + { + // need to make dummy on-heap copy + scratch = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!scratch) return 0; + } + + // copy string to zero-terminated buffer and perform lookup + memcpy(scratch, begin, length * sizeof(char_t)); + scratch[length] = 0; + + xpath_variable* result = set->get(scratch); + + // free dummy buffer + if (scratch != buffer) xml_memory::deallocate(scratch); + + return result; + } +PUGI__NS_END + +// Internal node set class +PUGI__NS_BEGIN + PUGI__FN xpath_node_set::type_t xpath_get_order(const xpath_node* begin, const xpath_node* end) + { + if (end - begin < 2) + return xpath_node_set::type_sorted; + + document_order_comparator cmp; + + bool first = cmp(begin[0], begin[1]); + + for (const xpath_node* it = begin + 1; it + 1 < end; ++it) + if (cmp(it[0], it[1]) != first) + return xpath_node_set::type_unsorted; + + return first ? xpath_node_set::type_sorted : xpath_node_set::type_sorted_reverse; + } + + PUGI__FN xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool rev) + { + xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; + + if (type == xpath_node_set::type_unsorted) + { + xpath_node_set::type_t sorted = xpath_get_order(begin, end); + + if (sorted == xpath_node_set::type_unsorted) + { + sort(begin, end, document_order_comparator()); + + type = xpath_node_set::type_sorted; + } + else + type = sorted; + } + + if (type != order) reverse(begin, end); + + return order; + } + + PUGI__FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type) + { + if (begin == end) return xpath_node(); + + switch (type) + { + case xpath_node_set::type_sorted: + return *begin; + + case xpath_node_set::type_sorted_reverse: + return *(end - 1); + + case xpath_node_set::type_unsorted: + return *min_element(begin, end, document_order_comparator()); + + default: + assert(!"Invalid node set type"); + return xpath_node(); + } + } + + class xpath_node_set_raw + { + xpath_node_set::type_t _type; + + xpath_node* _begin; + xpath_node* _end; + xpath_node* _eos; + + public: + xpath_node_set_raw(): _type(xpath_node_set::type_unsorted), _begin(0), _end(0), _eos(0) + { + } + + xpath_node* begin() const + { + return _begin; + } + + xpath_node* end() const + { + return _end; + } + + bool empty() const + { + return _begin == _end; + } + + size_t size() const + { + return static_cast(_end - _begin); + } + + xpath_node first() const + { + return xpath_first(_begin, _end, _type); + } + + void push_back_grow(const xpath_node& node, xpath_allocator* alloc); + + void push_back(const xpath_node& node, xpath_allocator* alloc) + { + if (_end != _eos) + *_end++ = node; + else + push_back_grow(node, alloc); + } + + void append(const xpath_node* begin_, const xpath_node* end_, xpath_allocator* alloc) + { + if (begin_ == end_) return; + + size_t size_ = static_cast(_end - _begin); + size_t capacity = static_cast(_eos - _begin); + size_t count = static_cast(end_ - begin_); + + if (size_ + count > capacity) + { + // reallocate the old array or allocate a new one + xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), (size_ + count) * sizeof(xpath_node))); + assert(data); + + // finalize + _begin = data; + _end = data + size_; + _eos = data + size_ + count; + } + + memcpy(_end, begin_, count * sizeof(xpath_node)); + _end += count; + } + + void sort_do() + { + _type = xpath_sort(_begin, _end, _type, false); + } + + void truncate(xpath_node* pos) + { + assert(_begin <= pos && pos <= _end); + + _end = pos; + } + + void remove_duplicates() + { + if (_type == xpath_node_set::type_unsorted) + sort(_begin, _end, duplicate_comparator()); + + _end = unique(_begin, _end); + } + + xpath_node_set::type_t type() const + { + return _type; + } + + void set_type(xpath_node_set::type_t value) + { + _type = value; + } + }; + + PUGI__FN_NO_INLINE void xpath_node_set_raw::push_back_grow(const xpath_node& node, xpath_allocator* alloc) + { + size_t capacity = static_cast(_eos - _begin); + + // get new capacity (1.5x rule) + size_t new_capacity = capacity + capacity / 2 + 1; + + // reallocate the old array or allocate a new one + xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); + assert(data); + + // finalize + _begin = data; + _end = data + capacity; + _eos = data + new_capacity; + + // push + *_end++ = node; + } +PUGI__NS_END + +PUGI__NS_BEGIN + struct xpath_context + { + xpath_node n; + size_t position, size; + + xpath_context(const xpath_node& n_, size_t position_, size_t size_): n(n_), position(position_), size(size_) + { + } + }; + + enum lexeme_t + { + lex_none = 0, + lex_equal, + lex_not_equal, + lex_less, + lex_greater, + lex_less_or_equal, + lex_greater_or_equal, + lex_plus, + lex_minus, + lex_multiply, + lex_union, + lex_var_ref, + lex_open_brace, + lex_close_brace, + lex_quoted_string, + lex_number, + lex_slash, + lex_double_slash, + lex_open_square_brace, + lex_close_square_brace, + lex_string, + lex_comma, + lex_axis_attribute, + lex_dot, + lex_double_dot, + lex_double_colon, + lex_eof + }; + + struct xpath_lexer_string + { + const char_t* begin; + const char_t* end; + + xpath_lexer_string(): begin(0), end(0) + { + } + + bool operator==(const char_t* other) const + { + size_t length = static_cast(end - begin); + + return strequalrange(other, begin, length); + } + }; + + class xpath_lexer + { + const char_t* _cur; + const char_t* _cur_lexeme_pos; + xpath_lexer_string _cur_lexeme_contents; + + lexeme_t _cur_lexeme; + + public: + explicit xpath_lexer(const char_t* query): _cur(query) + { + next(); + } + + const char_t* state() const + { + return _cur; + } + + void next() + { + const char_t* cur = _cur; + + while (PUGI__IS_CHARTYPE(*cur, ct_space)) ++cur; + + // save lexeme position for error reporting + _cur_lexeme_pos = cur; + + switch (*cur) + { + case 0: + _cur_lexeme = lex_eof; + break; + + case '>': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_greater_or_equal; + } + else + { + cur += 1; + _cur_lexeme = lex_greater; + } + break; + + case '<': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_less_or_equal; + } + else + { + cur += 1; + _cur_lexeme = lex_less; + } + break; + + case '!': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_not_equal; + } + else + { + _cur_lexeme = lex_none; + } + break; + + case '=': + cur += 1; + _cur_lexeme = lex_equal; + + break; + + case '+': + cur += 1; + _cur_lexeme = lex_plus; + + break; + + case '-': + cur += 1; + _cur_lexeme = lex_minus; + + break; + + case '*': + cur += 1; + _cur_lexeme = lex_multiply; + + break; + + case '|': + cur += 1; + _cur_lexeme = lex_union; + + break; + + case '$': + cur += 1; + + if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) + { + _cur_lexeme_contents.begin = cur; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + + if (cur[0] == ':' && PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // qname + { + cur++; // : + + while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_var_ref; + } + else + { + _cur_lexeme = lex_none; + } + + break; + + case '(': + cur += 1; + _cur_lexeme = lex_open_brace; + + break; + + case ')': + cur += 1; + _cur_lexeme = lex_close_brace; + + break; + + case '[': + cur += 1; + _cur_lexeme = lex_open_square_brace; + + break; + + case ']': + cur += 1; + _cur_lexeme = lex_close_square_brace; + + break; + + case ',': + cur += 1; + _cur_lexeme = lex_comma; + + break; + + case '/': + if (*(cur+1) == '/') + { + cur += 2; + _cur_lexeme = lex_double_slash; + } + else + { + cur += 1; + _cur_lexeme = lex_slash; + } + break; + + case '.': + if (*(cur+1) == '.') + { + cur += 2; + _cur_lexeme = lex_double_dot; + } + else if (PUGI__IS_CHARTYPEX(*(cur+1), ctx_digit)) + { + _cur_lexeme_contents.begin = cur; // . + + ++cur; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_number; + } + else + { + cur += 1; + _cur_lexeme = lex_dot; + } + break; + + case '@': + cur += 1; + _cur_lexeme = lex_axis_attribute; + + break; + + case '"': + case '\'': + { + char_t terminator = *cur; + + ++cur; + + _cur_lexeme_contents.begin = cur; + while (*cur && *cur != terminator) cur++; + _cur_lexeme_contents.end = cur; + + if (!*cur) + _cur_lexeme = lex_none; + else + { + cur += 1; + _cur_lexeme = lex_quoted_string; + } + + break; + } + + case ':': + if (*(cur+1) == ':') + { + cur += 2; + _cur_lexeme = lex_double_colon; + } + else + { + _cur_lexeme = lex_none; + } + break; + + default: + if (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) + { + _cur_lexeme_contents.begin = cur; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + + if (*cur == '.') + { + cur++; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_number; + } + else if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) + { + _cur_lexeme_contents.begin = cur; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + + if (cur[0] == ':') + { + if (cur[1] == '*') // namespace test ncname:* + { + cur += 2; // :* + } + else if (PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // namespace test qname + { + cur++; // : + + while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + } + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_string; + } + else + { + _cur_lexeme = lex_none; + } + } + + _cur = cur; + } + + lexeme_t current() const + { + return _cur_lexeme; + } + + const char_t* current_pos() const + { + return _cur_lexeme_pos; + } + + const xpath_lexer_string& contents() const + { + assert(_cur_lexeme == lex_var_ref || _cur_lexeme == lex_number || _cur_lexeme == lex_string || _cur_lexeme == lex_quoted_string); + + return _cur_lexeme_contents; + } + }; + + enum ast_type_t + { + ast_unknown, + ast_op_or, // left or right + ast_op_and, // left and right + ast_op_equal, // left = right + ast_op_not_equal, // left != right + ast_op_less, // left < right + ast_op_greater, // left > right + ast_op_less_or_equal, // left <= right + ast_op_greater_or_equal, // left >= right + ast_op_add, // left + right + ast_op_subtract, // left - right + ast_op_multiply, // left * right + ast_op_divide, // left / right + ast_op_mod, // left % right + ast_op_negate, // left - right + ast_op_union, // left | right + ast_predicate, // apply predicate to set; next points to next predicate + ast_filter, // select * from left where right + ast_string_constant, // string constant + ast_number_constant, // number constant + ast_variable, // variable + ast_func_last, // last() + ast_func_position, // position() + ast_func_count, // count(left) + ast_func_id, // id(left) + ast_func_local_name_0, // local-name() + ast_func_local_name_1, // local-name(left) + ast_func_namespace_uri_0, // namespace-uri() + ast_func_namespace_uri_1, // namespace-uri(left) + ast_func_name_0, // name() + ast_func_name_1, // name(left) + ast_func_string_0, // string() + ast_func_string_1, // string(left) + ast_func_concat, // concat(left, right, siblings) + ast_func_starts_with, // starts_with(left, right) + ast_func_contains, // contains(left, right) + ast_func_substring_before, // substring-before(left, right) + ast_func_substring_after, // substring-after(left, right) + ast_func_substring_2, // substring(left, right) + ast_func_substring_3, // substring(left, right, third) + ast_func_string_length_0, // string-length() + ast_func_string_length_1, // string-length(left) + ast_func_normalize_space_0, // normalize-space() + ast_func_normalize_space_1, // normalize-space(left) + ast_func_translate, // translate(left, right, third) + ast_func_boolean, // boolean(left) + ast_func_not, // not(left) + ast_func_true, // true() + ast_func_false, // false() + ast_func_lang, // lang(left) + ast_func_number_0, // number() + ast_func_number_1, // number(left) + ast_func_sum, // sum(left) + ast_func_floor, // floor(left) + ast_func_ceiling, // ceiling(left) + ast_func_round, // round(left) + ast_step, // process set left with step + ast_step_root, // select root node + + ast_opt_translate_table, // translate(left, right, third) where right/third are constants + ast_opt_compare_attribute // @name = 'string' + }; + + enum axis_t + { + axis_ancestor, + axis_ancestor_or_self, + axis_attribute, + axis_child, + axis_descendant, + axis_descendant_or_self, + axis_following, + axis_following_sibling, + axis_namespace, + axis_parent, + axis_preceding, + axis_preceding_sibling, + axis_self + }; + + enum nodetest_t + { + nodetest_none, + nodetest_name, + nodetest_type_node, + nodetest_type_comment, + nodetest_type_pi, + nodetest_type_text, + nodetest_pi, + nodetest_all, + nodetest_all_in_namespace + }; + + enum predicate_t + { + predicate_default, + predicate_posinv, + predicate_constant, + predicate_constant_one + }; + + enum nodeset_eval_t + { + nodeset_eval_all, + nodeset_eval_any, + nodeset_eval_first + }; + + template struct axis_to_type + { + static const axis_t axis; + }; + + template const axis_t axis_to_type::axis = N; + + class xpath_ast_node + { + private: + // node type + char _type; + char _rettype; + + // for ast_step + char _axis; + + // for ast_step/ast_predicate/ast_filter + char _test; + + // tree node structure + xpath_ast_node* _left; + xpath_ast_node* _right; + xpath_ast_node* _next; + + union + { + // value for ast_string_constant + const char_t* string; + // value for ast_number_constant + double number; + // variable for ast_variable + xpath_variable* variable; + // node test for ast_step (node name/namespace/node type/pi target) + const char_t* nodetest; + // table for ast_opt_translate_table + const unsigned char* table; + } _data; + + xpath_ast_node(const xpath_ast_node&); + xpath_ast_node& operator=(const xpath_ast_node&); + + template static bool compare_eq(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) + { + xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); + + if (lt != xpath_type_node_set && rt != xpath_type_node_set) + { + if (lt == xpath_type_boolean || rt == xpath_type_boolean) + return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); + else if (lt == xpath_type_number || rt == xpath_type_number) + return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); + else if (lt == xpath_type_string || rt == xpath_type_string) + { + xpath_allocator_capture cr(stack.result); + + xpath_string ls = lhs->eval_string(c, stack); + xpath_string rs = rhs->eval_string(c, stack); + + return comp(ls, rs); + } + } + else if (lt == xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(string_value(*li, stack.result), string_value(*ri, stack.result))) + return true; + } + + return false; + } + else + { + if (lt == xpath_type_node_set) + { + swap(lhs, rhs); + swap(lt, rt); + } + + if (lt == xpath_type_boolean) + return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); + else if (lt == xpath_type_number) + { + xpath_allocator_capture cr(stack.result); + + double l = lhs->eval_number(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + + return false; + } + else if (lt == xpath_type_string) + { + xpath_allocator_capture cr(stack.result); + + xpath_string l = lhs->eval_string(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, string_value(*ri, stack.result))) + return true; + } + + return false; + } + } + + assert(!"Wrong types"); + return false; + } + + static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval) + { + return type == xpath_node_set::type_sorted ? eval != nodeset_eval_all : eval == nodeset_eval_any; + } + + template static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) + { + xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); + + if (lt != xpath_type_node_set && rt != xpath_type_node_set) + return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); + else if (lt == xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + { + xpath_allocator_capture cri(stack.result); + + double l = convert_string_to_number(string_value(*li, stack.result).c_str()); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture crii(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + } + + return false; + } + else if (lt != xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + double l = lhs->eval_number(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + + return false; + } + else if (lt == xpath_type_node_set && rt != xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); + double r = rhs->eval_number(c, stack); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + { + xpath_allocator_capture cri(stack.result); + + if (comp(convert_string_to_number(string_value(*li, stack.result).c_str()), r)) + return true; + } + + return false; + } + else + { + assert(!"Wrong types"); + return false; + } + } + + static void apply_predicate_boolean(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once) + { + assert(ns.size() >= first); + assert(expr->rettype() != xpath_type_number); + + size_t i = 1; + size_t size = ns.size() - first; + + xpath_node* last = ns.begin() + first; + + // remove_if... or well, sort of + for (xpath_node* it = last; it != ns.end(); ++it, ++i) + { + xpath_context c(*it, i, size); + + if (expr->eval_boolean(c, stack)) + { + *last++ = *it; + + if (once) break; + } + } + + ns.truncate(last); + } + + static void apply_predicate_number(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once) + { + assert(ns.size() >= first); + assert(expr->rettype() == xpath_type_number); + + size_t i = 1; + size_t size = ns.size() - first; + + xpath_node* last = ns.begin() + first; + + // remove_if... or well, sort of + for (xpath_node* it = last; it != ns.end(); ++it, ++i) + { + xpath_context c(*it, i, size); + + if (expr->eval_number(c, stack) == i) + { + *last++ = *it; + + if (once) break; + } + } + + ns.truncate(last); + } + + static void apply_predicate_number_const(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack) + { + assert(ns.size() >= first); + assert(expr->rettype() == xpath_type_number); + + size_t size = ns.size() - first; + + xpath_node* last = ns.begin() + first; + + xpath_context c(xpath_node(), 1, size); + + double er = expr->eval_number(c, stack); + + if (er >= 1.0 && er <= size) + { + size_t eri = static_cast(er); + + if (er == eri) + { + xpath_node r = last[eri - 1]; + + *last++ = r; + } + } + + ns.truncate(last); + } + + void apply_predicate(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, bool once) + { + if (ns.size() == first) return; + + assert(_type == ast_filter || _type == ast_predicate); + + if (_test == predicate_constant || _test == predicate_constant_one) + apply_predicate_number_const(ns, first, _right, stack); + else if (_right->rettype() == xpath_type_number) + apply_predicate_number(ns, first, _right, stack, once); + else + apply_predicate_boolean(ns, first, _right, stack, once); + } + + void apply_predicates(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, nodeset_eval_t eval) + { + if (ns.size() == first) return; + + bool last_once = eval_once(ns.type(), eval); + + for (xpath_ast_node* pred = _right; pred; pred = pred->_next) + pred->apply_predicate(ns, first, stack, !pred->_next && last_once); + } + + bool step_push(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* parent, xpath_allocator* alloc) + { + assert(a); + + const char_t* name = a->name ? a->name : PUGIXML_TEXT(""); + + switch (_test) + { + case nodetest_name: + if (strequal(name, _data.nodetest) && is_xpath_attribute(name)) + { + ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); + return true; + } + break; + + case nodetest_type_node: + case nodetest_all: + if (is_xpath_attribute(name)) + { + ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); + return true; + } + break; + + case nodetest_all_in_namespace: + if (starts_with(name, _data.nodetest) && is_xpath_attribute(name)) + { + ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); + return true; + } + break; + + default: + ; + } + + return false; + } + + bool step_push(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc) + { + assert(n); + + xml_node_type type = PUGI__NODETYPE(n); + + switch (_test) + { + case nodetest_name: + if (type == node_element && n->name && strequal(n->name, _data.nodetest)) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_type_node: + ns.push_back(xml_node(n), alloc); + return true; + + case nodetest_type_comment: + if (type == node_comment) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_type_text: + if (type == node_pcdata || type == node_cdata) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_type_pi: + if (type == node_pi) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_pi: + if (type == node_pi && n->name && strequal(n->name, _data.nodetest)) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_all: + if (type == node_element) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_all_in_namespace: + if (type == node_element && n->name && starts_with(n->name, _data.nodetest)) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + default: + assert(!"Unknown axis"); + } + + return false; + } + + template void step_fill(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc, bool once, T) + { + const axis_t axis = T::axis; + + switch (axis) + { + case axis_attribute: + { + for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute) + if (step_push(ns, a, n, alloc) & once) + return; + + break; + } + + case axis_child: + { + for (xml_node_struct* c = n->first_child; c; c = c->next_sibling) + if (step_push(ns, c, alloc) & once) + return; + + break; + } + + case axis_descendant: + case axis_descendant_or_self: + { + if (axis == axis_descendant_or_self) + if (step_push(ns, n, alloc) & once) + return; + + xml_node_struct* cur = n->first_child; + + while (cur) + { + if (step_push(ns, cur, alloc) & once) + return; + + if (cur->first_child) + cur = cur->first_child; + else + { + while (!cur->next_sibling) + { + cur = cur->parent; + + if (cur == n) return; + } + + cur = cur->next_sibling; + } + } + + break; + } + + case axis_following_sibling: + { + for (xml_node_struct* c = n->next_sibling; c; c = c->next_sibling) + if (step_push(ns, c, alloc) & once) + return; + + break; + } + + case axis_preceding_sibling: + { + for (xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c) + if (step_push(ns, c, alloc) & once) + return; + + break; + } + + case axis_following: + { + xml_node_struct* cur = n; + + // exit from this node so that we don't include descendants + while (!cur->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + } + + cur = cur->next_sibling; + + while (cur) + { + if (step_push(ns, cur, alloc) & once) + return; + + if (cur->first_child) + cur = cur->first_child; + else + { + while (!cur->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + } + + cur = cur->next_sibling; + } + } + + break; + } + + case axis_preceding: + { + xml_node_struct* cur = n; + + // exit from this node so that we don't include descendants + while (!cur->prev_sibling_c->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + } + + cur = cur->prev_sibling_c; + + while (cur) + { + if (cur->first_child) + cur = cur->first_child->prev_sibling_c; + else + { + // leaf node, can't be ancestor + if (step_push(ns, cur, alloc) & once) + return; + + while (!cur->prev_sibling_c->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + + if (!node_is_ancestor(cur, n)) + if (step_push(ns, cur, alloc) & once) + return; + } + + cur = cur->prev_sibling_c; + } + } + + break; + } + + case axis_ancestor: + case axis_ancestor_or_self: + { + if (axis == axis_ancestor_or_self) + if (step_push(ns, n, alloc) & once) + return; + + xml_node_struct* cur = n->parent; + + while (cur) + { + if (step_push(ns, cur, alloc) & once) + return; + + cur = cur->parent; + } + + break; + } + + case axis_self: + { + step_push(ns, n, alloc); + + break; + } + + case axis_parent: + { + if (n->parent) + step_push(ns, n->parent, alloc); + + break; + } + + default: + assert(!"Unimplemented axis"); + } + } + + template void step_fill(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* p, xpath_allocator* alloc, bool once, T v) + { + const axis_t axis = T::axis; + + switch (axis) + { + case axis_ancestor: + case axis_ancestor_or_self: + { + if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test + if (step_push(ns, a, p, alloc) & once) + return; + + xml_node_struct* cur = p; + + while (cur) + { + if (step_push(ns, cur, alloc) & once) + return; + + cur = cur->parent; + } + + break; + } + + case axis_descendant_or_self: + case axis_self: + { + if (_test == nodetest_type_node) // reject attributes based on principal node type test + step_push(ns, a, p, alloc); + + break; + } + + case axis_following: + { + xml_node_struct* cur = p; + + while (cur) + { + if (cur->first_child) + cur = cur->first_child; + else + { + while (!cur->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + } + + cur = cur->next_sibling; + } + + if (step_push(ns, cur, alloc) & once) + return; + } + + break; + } + + case axis_parent: + { + step_push(ns, p, alloc); + + break; + } + + case axis_preceding: + { + // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding + step_fill(ns, p, alloc, once, v); + break; + } + + default: + assert(!"Unimplemented axis"); + } + } + + template void step_fill(xpath_node_set_raw& ns, const xpath_node& xn, xpath_allocator* alloc, bool once, T v) + { + const axis_t axis = T::axis; + const bool axis_has_attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self); + + if (xn.node()) + step_fill(ns, xn.node().internal_object(), alloc, once, v); + else if (axis_has_attributes && xn.attribute() && xn.parent()) + step_fill(ns, xn.attribute().internal_object(), xn.parent().internal_object(), alloc, once, v); + } + + template xpath_node_set_raw step_do(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval, T v) + { + const axis_t axis = T::axis; + const bool axis_reverse = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling); + const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; + + bool once = + (axis == axis_attribute && _test == nodetest_name) || + (!_right && eval_once(axis_type, eval)) || + (_right && !_right->_next && _right->_test == predicate_constant_one); + + xpath_node_set_raw ns; + ns.set_type(axis_type); + + if (_left) + { + xpath_node_set_raw s = _left->eval_node_set(c, stack, nodeset_eval_all); + + // self axis preserves the original order + if (axis == axis_self) ns.set_type(s.type()); + + for (const xpath_node* it = s.begin(); it != s.end(); ++it) + { + size_t size = ns.size(); + + // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes + if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted); + + step_fill(ns, *it, stack.result, once, v); + if (_right) apply_predicates(ns, size, stack, eval); + } + } + else + { + step_fill(ns, c.n, stack.result, once, v); + if (_right) apply_predicates(ns, 0, stack, eval); + } + + // child, attribute and self axes always generate unique set of nodes + // for other axis, if the set stayed sorted, it stayed unique because the traversal algorithms do not visit the same node twice + if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted) + ns.remove_duplicates(); + + return ns; + } + + public: + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t* value): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_string_constant); + _data.string = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_number_constant); + _data.number = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable* value): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_variable); + _data.variable = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = 0, xpath_ast_node* right = 0): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0) + { + } + + xpath_ast_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents): + _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(static_cast(axis)), _test(static_cast(test)), _left(left), _right(0), _next(0) + { + assert(type == ast_step); + _data.nodetest = contents; + } + + xpath_ast_node(ast_type_t type, xpath_ast_node* left, xpath_ast_node* right, predicate_t test): + _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(0), _test(static_cast(test)), _left(left), _right(right), _next(0) + { + assert(type == ast_filter || type == ast_predicate); + } + + void set_next(xpath_ast_node* value) + { + _next = value; + } + + void set_right(xpath_ast_node* value) + { + _right = value; + } + + bool eval_boolean(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_op_or: + return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack); + + case ast_op_and: + return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack); + + case ast_op_equal: + return compare_eq(_left, _right, c, stack, equal_to()); + + case ast_op_not_equal: + return compare_eq(_left, _right, c, stack, not_equal_to()); + + case ast_op_less: + return compare_rel(_left, _right, c, stack, less()); + + case ast_op_greater: + return compare_rel(_right, _left, c, stack, less()); + + case ast_op_less_or_equal: + return compare_rel(_left, _right, c, stack, less_equal()); + + case ast_op_greater_or_equal: + return compare_rel(_right, _left, c, stack, less_equal()); + + case ast_func_starts_with: + { + xpath_allocator_capture cr(stack.result); + + xpath_string lr = _left->eval_string(c, stack); + xpath_string rr = _right->eval_string(c, stack); + + return starts_with(lr.c_str(), rr.c_str()); + } + + case ast_func_contains: + { + xpath_allocator_capture cr(stack.result); + + xpath_string lr = _left->eval_string(c, stack); + xpath_string rr = _right->eval_string(c, stack); + + return find_substring(lr.c_str(), rr.c_str()) != 0; + } + + case ast_func_boolean: + return _left->eval_boolean(c, stack); + + case ast_func_not: + return !_left->eval_boolean(c, stack); + + case ast_func_true: + return true; + + case ast_func_false: + return false; + + case ast_func_lang: + { + if (c.n.attribute()) return false; + + xpath_allocator_capture cr(stack.result); + + xpath_string lang = _left->eval_string(c, stack); + + for (xml_node n = c.n.node(); n; n = n.parent()) + { + xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang")); + + if (a) + { + const char_t* value = a.value(); + + // strnicmp / strncasecmp is not portable + for (const char_t* lit = lang.c_str(); *lit; ++lit) + { + if (tolower_ascii(*lit) != tolower_ascii(*value)) return false; + ++value; + } + + return *value == 0 || *value == '-'; + } + } + + return false; + } + + case ast_opt_compare_attribute: + { + const char_t* value = (_right->_type == ast_string_constant) ? _right->_data.string : _right->_data.variable->get_string(); + + xml_attribute attr = c.n.node().attribute(_left->_data.nodetest); + + return attr && strequal(attr.value(), value) && is_xpath_attribute(attr.name()); + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_boolean) + return _data.variable->get_boolean(); + } + // fallthrough + + default: + { + switch (_rettype) + { + case xpath_type_number: + return convert_number_to_boolean(eval_number(c, stack)); + + case xpath_type_string: + { + xpath_allocator_capture cr(stack.result); + + return !eval_string(c, stack).empty(); + } + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.result); + + return !eval_node_set(c, stack, nodeset_eval_any).empty(); + } + + default: + assert(!"Wrong expression for return type boolean"); + return false; + } + } + } + } + + double eval_number(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_op_add: + return _left->eval_number(c, stack) + _right->eval_number(c, stack); + + case ast_op_subtract: + return _left->eval_number(c, stack) - _right->eval_number(c, stack); + + case ast_op_multiply: + return _left->eval_number(c, stack) * _right->eval_number(c, stack); + + case ast_op_divide: + return _left->eval_number(c, stack) / _right->eval_number(c, stack); + + case ast_op_mod: + return fmod(_left->eval_number(c, stack), _right->eval_number(c, stack)); + + case ast_op_negate: + return -_left->eval_number(c, stack); + + case ast_number_constant: + return _data.number; + + case ast_func_last: + return static_cast(c.size); + + case ast_func_position: + return static_cast(c.position); + + case ast_func_count: + { + xpath_allocator_capture cr(stack.result); + + return static_cast(_left->eval_node_set(c, stack, nodeset_eval_all).size()); + } + + case ast_func_string_length_0: + { + xpath_allocator_capture cr(stack.result); + + return static_cast(string_value(c.n, stack.result).length()); + } + + case ast_func_string_length_1: + { + xpath_allocator_capture cr(stack.result); + + return static_cast(_left->eval_string(c, stack).length()); + } + + case ast_func_number_0: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(string_value(c.n, stack.result).c_str()); + } + + case ast_func_number_1: + return _left->eval_number(c, stack); + + case ast_func_sum: + { + xpath_allocator_capture cr(stack.result); + + double r = 0; + + xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* it = ns.begin(); it != ns.end(); ++it) + { + xpath_allocator_capture cri(stack.result); + + r += convert_string_to_number(string_value(*it, stack.result).c_str()); + } + + return r; + } + + case ast_func_floor: + { + double r = _left->eval_number(c, stack); + + return r == r ? floor(r) : r; + } + + case ast_func_ceiling: + { + double r = _left->eval_number(c, stack); + + return r == r ? ceil(r) : r; + } + + case ast_func_round: + return round_nearest_nzero(_left->eval_number(c, stack)); + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_number) + return _data.variable->get_number(); + } + // fallthrough + + default: + { + switch (_rettype) + { + case xpath_type_boolean: + return eval_boolean(c, stack) ? 1 : 0; + + case xpath_type_string: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(eval_string(c, stack).c_str()); + } + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(eval_string(c, stack).c_str()); + } + + default: + assert(!"Wrong expression for return type number"); + return 0; + } + + } + } + } + + xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) + { + assert(_type == ast_func_concat); + + xpath_allocator_capture ct(stack.temp); + + // count the string number + size_t count = 1; + for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++; + + // gather all strings + xpath_string static_buffer[4]; + xpath_string* buffer = static_buffer; + + // allocate on-heap for large concats + if (count > sizeof(static_buffer) / sizeof(static_buffer[0])) + { + buffer = static_cast(stack.temp->allocate(count * sizeof(xpath_string))); + assert(buffer); + } + + // evaluate all strings to temporary stack + xpath_stack swapped_stack = {stack.temp, stack.result}; + + buffer[0] = _left->eval_string(c, swapped_stack); + + size_t pos = 1; + for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack); + assert(pos == count); + + // get total length + size_t length = 0; + for (size_t i = 0; i < count; ++i) length += buffer[i].length(); + + // create final string + char_t* result = static_cast(stack.result->allocate((length + 1) * sizeof(char_t))); + assert(result); + + char_t* ri = result; + + for (size_t j = 0; j < count; ++j) + for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) + *ri++ = *bi; + + *ri = 0; + + return xpath_string::from_heap_preallocated(result, ri); + } + + xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_string_constant: + return xpath_string::from_const(_data.string); + + case ast_func_local_name_0: + { + xpath_node na = c.n; + + return xpath_string::from_const(local_name(na)); + } + + case ast_func_local_name_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); + xpath_node na = ns.first(); + + return xpath_string::from_const(local_name(na)); + } + + case ast_func_name_0: + { + xpath_node na = c.n; + + return xpath_string::from_const(qualified_name(na)); + } + + case ast_func_name_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); + xpath_node na = ns.first(); + + return xpath_string::from_const(qualified_name(na)); + } + + case ast_func_namespace_uri_0: + { + xpath_node na = c.n; + + return xpath_string::from_const(namespace_uri(na)); + } + + case ast_func_namespace_uri_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); + xpath_node na = ns.first(); + + return xpath_string::from_const(namespace_uri(na)); + } + + case ast_func_string_0: + return string_value(c.n, stack.result); + + case ast_func_string_1: + return _left->eval_string(c, stack); + + case ast_func_concat: + return eval_string_concat(c, stack); + + case ast_func_substring_before: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + xpath_string p = _right->eval_string(c, swapped_stack); + + const char_t* pos = find_substring(s.c_str(), p.c_str()); + + return pos ? xpath_string::from_heap(s.c_str(), pos, stack.result) : xpath_string(); + } + + case ast_func_substring_after: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + xpath_string p = _right->eval_string(c, swapped_stack); + + const char_t* pos = find_substring(s.c_str(), p.c_str()); + if (!pos) return xpath_string(); + + const char_t* rbegin = pos + p.length(); + const char_t* rend = s.c_str() + s.length(); + + return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); + } + + case ast_func_substring_2: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + size_t s_length = s.length(); + + double first = round_nearest(_right->eval_number(c, stack)); + + if (is_nan(first)) return xpath_string(); // NaN + else if (first >= s_length + 1) return xpath_string(); + + size_t pos = first < 1 ? 1 : static_cast(first); + assert(1 <= pos && pos <= s_length + 1); + + const char_t* rbegin = s.c_str() + (pos - 1); + const char_t* rend = s.c_str() + s.length(); + + return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); + } + + case ast_func_substring_3: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + size_t s_length = s.length(); + + double first = round_nearest(_right->eval_number(c, stack)); + double last = first + round_nearest(_right->_next->eval_number(c, stack)); + + if (is_nan(first) || is_nan(last)) return xpath_string(); + else if (first >= s_length + 1) return xpath_string(); + else if (first >= last) return xpath_string(); + else if (last < 1) return xpath_string(); + + size_t pos = first < 1 ? 1 : static_cast(first); + size_t end = last >= s_length + 1 ? s_length + 1 : static_cast(last); + + assert(1 <= pos && pos <= end && end <= s_length + 1); + const char_t* rbegin = s.c_str() + (pos - 1); + const char_t* rend = s.c_str() + (end - 1); + + return (end == s_length + 1 && !s.uses_heap()) ? xpath_string::from_const(rbegin) : xpath_string::from_heap(rbegin, rend, stack.result); + } + + case ast_func_normalize_space_0: + { + xpath_string s = string_value(c.n, stack.result); + + normalize_space(s.data(stack.result)); + + return s; + } + + case ast_func_normalize_space_1: + { + xpath_string s = _left->eval_string(c, stack); + + normalize_space(s.data(stack.result)); + + return s; + } + + case ast_func_translate: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, stack); + xpath_string from = _right->eval_string(c, swapped_stack); + xpath_string to = _right->_next->eval_string(c, swapped_stack); + + translate(s.data(stack.result), from.c_str(), to.c_str(), to.length()); + + return s; + } + + case ast_opt_translate_table: + { + xpath_string s = _left->eval_string(c, stack); + + translate_table(s.data(stack.result), _data.table); + + return s; + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_string) + return xpath_string::from_const(_data.variable->get_string()); + } + // fallthrough + + default: + { + switch (_rettype) + { + case xpath_type_boolean: + return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); + + case xpath_type_number: + return convert_number_to_string(eval_number(c, stack), stack.result); + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first); + return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result); + } + + default: + assert(!"Wrong expression for return type string"); + return xpath_string(); + } + } + } + } + + xpath_node_set_raw eval_node_set(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval) + { + switch (_type) + { + case ast_op_union: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_node_set_raw ls = _left->eval_node_set(c, swapped_stack, eval); + xpath_node_set_raw rs = _right->eval_node_set(c, stack, eval); + + // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother + rs.set_type(xpath_node_set::type_unsorted); + + rs.append(ls.begin(), ls.end(), stack.result); + rs.remove_duplicates(); + + return rs; + } + + case ast_filter: + { + xpath_node_set_raw set = _left->eval_node_set(c, stack, _test == predicate_constant_one ? nodeset_eval_first : nodeset_eval_all); + + // either expression is a number or it contains position() call; sort by document order + if (_test != predicate_posinv) set.sort_do(); + + bool once = eval_once(set.type(), eval); + + apply_predicate(set, 0, stack, once); + + return set; + } + + case ast_func_id: + return xpath_node_set_raw(); + + case ast_step: + { + switch (_axis) + { + case axis_ancestor: + return step_do(c, stack, eval, axis_to_type()); + + case axis_ancestor_or_self: + return step_do(c, stack, eval, axis_to_type()); + + case axis_attribute: + return step_do(c, stack, eval, axis_to_type()); + + case axis_child: + return step_do(c, stack, eval, axis_to_type()); + + case axis_descendant: + return step_do(c, stack, eval, axis_to_type()); + + case axis_descendant_or_self: + return step_do(c, stack, eval, axis_to_type()); + + case axis_following: + return step_do(c, stack, eval, axis_to_type()); + + case axis_following_sibling: + return step_do(c, stack, eval, axis_to_type()); + + case axis_namespace: + // namespaced axis is not supported + return xpath_node_set_raw(); + + case axis_parent: + return step_do(c, stack, eval, axis_to_type()); + + case axis_preceding: + return step_do(c, stack, eval, axis_to_type()); + + case axis_preceding_sibling: + return step_do(c, stack, eval, axis_to_type()); + + case axis_self: + return step_do(c, stack, eval, axis_to_type()); + + default: + assert(!"Unknown axis"); + return xpath_node_set_raw(); + } + } + + case ast_step_root: + { + assert(!_right); // root step can't have any predicates + + xpath_node_set_raw ns; + + ns.set_type(xpath_node_set::type_sorted); + + if (c.n.node()) ns.push_back(c.n.node().root(), stack.result); + else if (c.n.attribute()) ns.push_back(c.n.parent().root(), stack.result); + + return ns; + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_node_set) + { + const xpath_node_set& s = _data.variable->get_node_set(); + + xpath_node_set_raw ns; + + ns.set_type(s.type()); + ns.append(s.begin(), s.end(), stack.result); + + return ns; + } + } + // fallthrough + + default: + assert(!"Wrong expression for return type node set"); + return xpath_node_set_raw(); + } + } + + void optimize(xpath_allocator* alloc) + { + if (_left) _left->optimize(alloc); + if (_right) _right->optimize(alloc); + if (_next) _next->optimize(alloc); + + // Rewrite [position()=expr] with [expr] + // Note that this step has to go before classification to recognize [position()=1] + if ((_type == ast_filter || _type == ast_predicate) && + _right->_type == ast_op_equal && _right->_left->_type == ast_func_position && _right->_right->_rettype == xpath_type_number) + { + _right = _right->_right; + } + + // Classify filter/predicate ops to perform various optimizations during evaluation + if (_type == ast_filter || _type == ast_predicate) + { + assert(_test == predicate_default); + + if (_right->_type == ast_number_constant && _right->_data.number == 1.0) + _test = predicate_constant_one; + else if (_right->_rettype == xpath_type_number && (_right->_type == ast_number_constant || _right->_type == ast_variable || _right->_type == ast_func_last)) + _test = predicate_constant; + else if (_right->_rettype != xpath_type_number && _right->is_posinv_expr()) + _test = predicate_posinv; + } + + // Rewrite descendant-or-self::node()/child::foo with descendant::foo + // The former is a full form of //foo, the latter is much faster since it executes the node test immediately + // Do a similar kind of rewrite for self/descendant/descendant-or-self axes + // Note that we only rewrite positionally invariant steps (//foo[1] != /descendant::foo[1]) + if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) && _left && + _left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right && + is_posinv_step()) + { + if (_axis == axis_child || _axis == axis_descendant) + _axis = axis_descendant; + else + _axis = axis_descendant_or_self; + + _left = _left->_left; + } + + // Use optimized lookup table implementation for translate() with constant arguments + if (_type == ast_func_translate && _right->_type == ast_string_constant && _right->_next->_type == ast_string_constant) + { + unsigned char* table = translate_table_generate(alloc, _right->_data.string, _right->_next->_data.string); + + if (table) + { + _type = ast_opt_translate_table; + _data.table = table; + } + } + + // Use optimized path for @attr = 'value' or @attr = $value + if (_type == ast_op_equal && + _left->_type == ast_step && _left->_axis == axis_attribute && _left->_test == nodetest_name && !_left->_left && !_left->_right && + (_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string))) + { + _type = ast_opt_compare_attribute; + } + } + + bool is_posinv_expr() const + { + switch (_type) + { + case ast_func_position: + case ast_func_last: + return false; + + case ast_string_constant: + case ast_number_constant: + case ast_variable: + return true; + + case ast_step: + case ast_step_root: + return true; + + case ast_predicate: + case ast_filter: + return true; + + default: + if (_left && !_left->is_posinv_expr()) return false; + + for (xpath_ast_node* n = _right; n; n = n->_next) + if (!n->is_posinv_expr()) return false; + + return true; + } + } + + bool is_posinv_step() const + { + assert(_type == ast_step); + + for (xpath_ast_node* n = _right; n; n = n->_next) + { + assert(n->_type == ast_predicate); + + if (n->_test != predicate_posinv) + return false; + } + + return true; + } + + xpath_value_type rettype() const + { + return static_cast(_rettype); + } + }; + + struct xpath_parser + { + xpath_allocator* _alloc; + xpath_lexer _lexer; + + const char_t* _query; + xpath_variable_set* _variables; + + xpath_parse_result* _result; + + char_t _scratch[32]; + + #ifdef PUGIXML_NO_EXCEPTIONS + jmp_buf _error_handler; + #endif + + void throw_error(const char* message) + { + _result->error = message; + _result->offset = _lexer.current_pos() - _query; + + #ifdef PUGIXML_NO_EXCEPTIONS + longjmp(_error_handler, 1); + #else + throw xpath_exception(*_result); + #endif + } + + void throw_error_oom() + { + #ifdef PUGIXML_NO_EXCEPTIONS + throw_error("Out of memory"); + #else + throw std::bad_alloc(); + #endif + } + + void* alloc_node() + { + void* result = _alloc->allocate_nothrow(sizeof(xpath_ast_node)); + + if (!result) throw_error_oom(); + + return result; + } + + const char_t* alloc_string(const xpath_lexer_string& value) + { + if (value.begin) + { + size_t length = static_cast(value.end - value.begin); + + char_t* c = static_cast(_alloc->allocate_nothrow((length + 1) * sizeof(char_t))); + if (!c) throw_error_oom(); + assert(c); // workaround for clang static analysis + + memcpy(c, value.begin, length * sizeof(char_t)); + c[length] = 0; + + return c; + } + else return 0; + } + + xpath_ast_node* parse_function_helper(ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node* args[2]) + { + assert(argc <= 1); + + if (argc == 1 && args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); + + return new (alloc_node()) xpath_ast_node(argc == 0 ? type0 : type1, xpath_type_string, args[0]); + } + + xpath_ast_node* parse_function(const xpath_lexer_string& name, size_t argc, xpath_ast_node* args[2]) + { + switch (name.begin[0]) + { + case 'b': + if (name == PUGIXML_TEXT("boolean") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_boolean, xpath_type_boolean, args[0]); + + break; + + case 'c': + if (name == PUGIXML_TEXT("count") && argc == 1) + { + if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); + return new (alloc_node()) xpath_ast_node(ast_func_count, xpath_type_number, args[0]); + } + else if (name == PUGIXML_TEXT("contains") && argc == 2) + return new (alloc_node()) xpath_ast_node(ast_func_contains, xpath_type_boolean, args[0], args[1]); + else if (name == PUGIXML_TEXT("concat") && argc >= 2) + return new (alloc_node()) xpath_ast_node(ast_func_concat, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("ceiling") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_ceiling, xpath_type_number, args[0]); + + break; + + case 'f': + if (name == PUGIXML_TEXT("false") && argc == 0) + return new (alloc_node()) xpath_ast_node(ast_func_false, xpath_type_boolean); + else if (name == PUGIXML_TEXT("floor") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_floor, xpath_type_number, args[0]); + + break; + + case 'i': + if (name == PUGIXML_TEXT("id") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_id, xpath_type_node_set, args[0]); + + break; + + case 'l': + if (name == PUGIXML_TEXT("last") && argc == 0) + return new (alloc_node()) xpath_ast_node(ast_func_last, xpath_type_number); + else if (name == PUGIXML_TEXT("lang") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_lang, xpath_type_boolean, args[0]); + else if (name == PUGIXML_TEXT("local-name") && argc <= 1) + return parse_function_helper(ast_func_local_name_0, ast_func_local_name_1, argc, args); + + break; + + case 'n': + if (name == PUGIXML_TEXT("name") && argc <= 1) + return parse_function_helper(ast_func_name_0, ast_func_name_1, argc, args); + else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1) + return parse_function_helper(ast_func_namespace_uri_0, ast_func_namespace_uri_1, argc, args); + else if (name == PUGIXML_TEXT("normalize-space") && argc <= 1) + return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("not") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_not, xpath_type_boolean, args[0]); + else if (name == PUGIXML_TEXT("number") && argc <= 1) + return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]); + + break; + + case 'p': + if (name == PUGIXML_TEXT("position") && argc == 0) + return new (alloc_node()) xpath_ast_node(ast_func_position, xpath_type_number); + + break; + + case 'r': + if (name == PUGIXML_TEXT("round") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_round, xpath_type_number, args[0]); + + break; + + case 's': + if (name == PUGIXML_TEXT("string") && argc <= 1) + return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]); + else if (name == PUGIXML_TEXT("string-length") && argc <= 1) + return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_number, args[0]); + else if (name == PUGIXML_TEXT("starts-with") && argc == 2) + return new (alloc_node()) xpath_ast_node(ast_func_starts_with, xpath_type_boolean, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring-before") && argc == 2) + return new (alloc_node()) xpath_ast_node(ast_func_substring_before, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring-after") && argc == 2) + return new (alloc_node()) xpath_ast_node(ast_func_substring_after, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring") && (argc == 2 || argc == 3)) + return new (alloc_node()) xpath_ast_node(argc == 2 ? ast_func_substring_2 : ast_func_substring_3, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("sum") && argc == 1) + { + if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); + return new (alloc_node()) xpath_ast_node(ast_func_sum, xpath_type_number, args[0]); + } + + break; + + case 't': + if (name == PUGIXML_TEXT("translate") && argc == 3) + return new (alloc_node()) xpath_ast_node(ast_func_translate, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("true") && argc == 0) + return new (alloc_node()) xpath_ast_node(ast_func_true, xpath_type_boolean); + + break; + + default: + break; + } + + throw_error("Unrecognized function or wrong parameter count"); + + return 0; + } + + axis_t parse_axis_name(const xpath_lexer_string& name, bool& specified) + { + specified = true; + + switch (name.begin[0]) + { + case 'a': + if (name == PUGIXML_TEXT("ancestor")) + return axis_ancestor; + else if (name == PUGIXML_TEXT("ancestor-or-self")) + return axis_ancestor_or_self; + else if (name == PUGIXML_TEXT("attribute")) + return axis_attribute; + + break; + + case 'c': + if (name == PUGIXML_TEXT("child")) + return axis_child; + + break; + + case 'd': + if (name == PUGIXML_TEXT("descendant")) + return axis_descendant; + else if (name == PUGIXML_TEXT("descendant-or-self")) + return axis_descendant_or_self; + + break; + + case 'f': + if (name == PUGIXML_TEXT("following")) + return axis_following; + else if (name == PUGIXML_TEXT("following-sibling")) + return axis_following_sibling; + + break; + + case 'n': + if (name == PUGIXML_TEXT("namespace")) + return axis_namespace; + + break; + + case 'p': + if (name == PUGIXML_TEXT("parent")) + return axis_parent; + else if (name == PUGIXML_TEXT("preceding")) + return axis_preceding; + else if (name == PUGIXML_TEXT("preceding-sibling")) + return axis_preceding_sibling; + + break; + + case 's': + if (name == PUGIXML_TEXT("self")) + return axis_self; + + break; + + default: + break; + } + + specified = false; + return axis_child; + } + + nodetest_t parse_node_test_type(const xpath_lexer_string& name) + { + switch (name.begin[0]) + { + case 'c': + if (name == PUGIXML_TEXT("comment")) + return nodetest_type_comment; + + break; + + case 'n': + if (name == PUGIXML_TEXT("node")) + return nodetest_type_node; + + break; + + case 'p': + if (name == PUGIXML_TEXT("processing-instruction")) + return nodetest_type_pi; + + break; + + case 't': + if (name == PUGIXML_TEXT("text")) + return nodetest_type_text; + + break; + + default: + break; + } + + return nodetest_none; + } + + // PrimaryExpr ::= VariableReference | '(' Expr ')' | Literal | Number | FunctionCall + xpath_ast_node* parse_primary_expression() + { + switch (_lexer.current()) + { + case lex_var_ref: + { + xpath_lexer_string name = _lexer.contents(); + + if (!_variables) + throw_error("Unknown variable: variable set is not provided"); + + xpath_variable* var = get_variable_scratch(_scratch, _variables, name.begin, name.end); + + if (!var) + throw_error("Unknown variable: variable set does not contain the given name"); + + _lexer.next(); + + return new (alloc_node()) xpath_ast_node(ast_variable, var->type(), var); + } + + case lex_open_brace: + { + _lexer.next(); + + xpath_ast_node* n = parse_expression(); + + if (_lexer.current() != lex_close_brace) + throw_error("Unmatched braces"); + + _lexer.next(); + + return n; + } + + case lex_quoted_string: + { + const char_t* value = alloc_string(_lexer.contents()); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_string_constant, xpath_type_string, value); + _lexer.next(); + + return n; + } + + case lex_number: + { + double value = 0; + + if (!convert_string_to_number_scratch(_scratch, _lexer.contents().begin, _lexer.contents().end, &value)) + throw_error_oom(); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_number_constant, xpath_type_number, value); + _lexer.next(); + + return n; + } + + case lex_string: + { + xpath_ast_node* args[2] = {0}; + size_t argc = 0; + + xpath_lexer_string function = _lexer.contents(); + _lexer.next(); + + xpath_ast_node* last_arg = 0; + + if (_lexer.current() != lex_open_brace) + throw_error("Unrecognized function call"); + _lexer.next(); + + if (_lexer.current() != lex_close_brace) + args[argc++] = parse_expression(); + + while (_lexer.current() != lex_close_brace) + { + if (_lexer.current() != lex_comma) + throw_error("No comma between function arguments"); + _lexer.next(); + + xpath_ast_node* n = parse_expression(); + + if (argc < 2) args[argc] = n; + else last_arg->set_next(n); + + argc++; + last_arg = n; + } + + _lexer.next(); + + return parse_function(function, argc, args); + } + + default: + throw_error("Unrecognizable primary expression"); + + return 0; + } + } + + // FilterExpr ::= PrimaryExpr | FilterExpr Predicate + // Predicate ::= '[' PredicateExpr ']' + // PredicateExpr ::= Expr + xpath_ast_node* parse_filter_expression() + { + xpath_ast_node* n = parse_primary_expression(); + + while (_lexer.current() == lex_open_square_brace) + { + _lexer.next(); + + xpath_ast_node* expr = parse_expression(); + + if (n->rettype() != xpath_type_node_set) throw_error("Predicate has to be applied to node set"); + + n = new (alloc_node()) xpath_ast_node(ast_filter, n, expr, predicate_default); + + if (_lexer.current() != lex_close_square_brace) + throw_error("Unmatched square brace"); + + _lexer.next(); + } + + return n; + } + + // Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep + // AxisSpecifier ::= AxisName '::' | '@'? + // NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' + // NameTest ::= '*' | NCName ':' '*' | QName + // AbbreviatedStep ::= '.' | '..' + xpath_ast_node* parse_step(xpath_ast_node* set) + { + if (set && set->rettype() != xpath_type_node_set) + throw_error("Step has to be applied to node set"); + + bool axis_specified = false; + axis_t axis = axis_child; // implied child axis + + if (_lexer.current() == lex_axis_attribute) + { + axis = axis_attribute; + axis_specified = true; + + _lexer.next(); + } + else if (_lexer.current() == lex_dot) + { + _lexer.next(); + + return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0); + } + else if (_lexer.current() == lex_double_dot) + { + _lexer.next(); + + return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0); + } + + nodetest_t nt_type = nodetest_none; + xpath_lexer_string nt_name; + + if (_lexer.current() == lex_string) + { + // node name test + nt_name = _lexer.contents(); + _lexer.next(); + + // was it an axis name? + if (_lexer.current() == lex_double_colon) + { + // parse axis name + if (axis_specified) throw_error("Two axis specifiers in one step"); + + axis = parse_axis_name(nt_name, axis_specified); + + if (!axis_specified) throw_error("Unknown axis"); + + // read actual node test + _lexer.next(); + + if (_lexer.current() == lex_multiply) + { + nt_type = nodetest_all; + nt_name = xpath_lexer_string(); + _lexer.next(); + } + else if (_lexer.current() == lex_string) + { + nt_name = _lexer.contents(); + _lexer.next(); + } + else throw_error("Unrecognized node test"); + } + + if (nt_type == nodetest_none) + { + // node type test or processing-instruction + if (_lexer.current() == lex_open_brace) + { + _lexer.next(); + + if (_lexer.current() == lex_close_brace) + { + _lexer.next(); + + nt_type = parse_node_test_type(nt_name); + + if (nt_type == nodetest_none) throw_error("Unrecognized node type"); + + nt_name = xpath_lexer_string(); + } + else if (nt_name == PUGIXML_TEXT("processing-instruction")) + { + if (_lexer.current() != lex_quoted_string) + throw_error("Only literals are allowed as arguments to processing-instruction()"); + + nt_type = nodetest_pi; + nt_name = _lexer.contents(); + _lexer.next(); + + if (_lexer.current() != lex_close_brace) + throw_error("Unmatched brace near processing-instruction()"); + _lexer.next(); + } + else + throw_error("Unmatched brace near node type test"); + + } + // QName or NCName:* + else + { + if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:* + { + nt_name.end--; // erase * + + nt_type = nodetest_all_in_namespace; + } + else nt_type = nodetest_name; + } + } + } + else if (_lexer.current() == lex_multiply) + { + nt_type = nodetest_all; + _lexer.next(); + } + else throw_error("Unrecognized node test"); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step, set, axis, nt_type, alloc_string(nt_name)); + + xpath_ast_node* last = 0; + + while (_lexer.current() == lex_open_square_brace) + { + _lexer.next(); + + xpath_ast_node* expr = parse_expression(); + + xpath_ast_node* pred = new (alloc_node()) xpath_ast_node(ast_predicate, 0, expr, predicate_default); + + if (_lexer.current() != lex_close_square_brace) + throw_error("Unmatched square brace"); + _lexer.next(); + + if (last) last->set_next(pred); + else n->set_right(pred); + + last = pred; + } + + return n; + } + + // RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step + xpath_ast_node* parse_relative_location_path(xpath_ast_node* set) + { + xpath_ast_node* n = parse_step(set); + + while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) + { + lexeme_t l = _lexer.current(); + _lexer.next(); + + if (l == lex_double_slash) + n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + + n = parse_step(n); + } + + return n; + } + + // LocationPath ::= RelativeLocationPath | AbsoluteLocationPath + // AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath + xpath_ast_node* parse_location_path() + { + if (_lexer.current() == lex_slash) + { + _lexer.next(); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); + + // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path + lexeme_t l = _lexer.current(); + + if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply) + return parse_relative_location_path(n); + else + return n; + } + else if (_lexer.current() == lex_double_slash) + { + _lexer.next(); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); + n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + + return parse_relative_location_path(n); + } + + // else clause moved outside of if because of bogus warning 'control may reach end of non-void function being inlined' in gcc 4.0.1 + return parse_relative_location_path(0); + } + + // PathExpr ::= LocationPath + // | FilterExpr + // | FilterExpr '/' RelativeLocationPath + // | FilterExpr '//' RelativeLocationPath + // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr + // UnaryExpr ::= UnionExpr | '-' UnaryExpr + xpath_ast_node* parse_path_or_unary_expression() + { + // Clarification. + // PathExpr begins with either LocationPath or FilterExpr. + // FilterExpr begins with PrimaryExpr + // PrimaryExpr begins with '$' in case of it being a variable reference, + // '(' in case of it being an expression, string literal, number constant or + // function call. + + if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || + _lexer.current() == lex_quoted_string || _lexer.current() == lex_number || + _lexer.current() == lex_string) + { + if (_lexer.current() == lex_string) + { + // This is either a function call, or not - if not, we shall proceed with location path + const char_t* state = _lexer.state(); + + while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state; + + if (*state != '(') return parse_location_path(); + + // This looks like a function call; however this still can be a node-test. Check it. + if (parse_node_test_type(_lexer.contents()) != nodetest_none) return parse_location_path(); + } + + xpath_ast_node* n = parse_filter_expression(); + + if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) + { + lexeme_t l = _lexer.current(); + _lexer.next(); + + if (l == lex_double_slash) + { + if (n->rettype() != xpath_type_node_set) throw_error("Step has to be applied to node set"); + + n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + } + + // select from location path + return parse_relative_location_path(n); + } + + return n; + } + else if (_lexer.current() == lex_minus) + { + _lexer.next(); + + // precedence 7+ - only parses union expressions + xpath_ast_node* expr = parse_expression_rec(parse_path_or_unary_expression(), 7); + + return new (alloc_node()) xpath_ast_node(ast_op_negate, xpath_type_number, expr); + } + else + return parse_location_path(); + } + + struct binary_op_t + { + ast_type_t asttype; + xpath_value_type rettype; + int precedence; + + binary_op_t(): asttype(ast_unknown), rettype(xpath_type_none), precedence(0) + { + } + + binary_op_t(ast_type_t asttype_, xpath_value_type rettype_, int precedence_): asttype(asttype_), rettype(rettype_), precedence(precedence_) + { + } + + static binary_op_t parse(xpath_lexer& lexer) + { + switch (lexer.current()) + { + case lex_string: + if (lexer.contents() == PUGIXML_TEXT("or")) + return binary_op_t(ast_op_or, xpath_type_boolean, 1); + else if (lexer.contents() == PUGIXML_TEXT("and")) + return binary_op_t(ast_op_and, xpath_type_boolean, 2); + else if (lexer.contents() == PUGIXML_TEXT("div")) + return binary_op_t(ast_op_divide, xpath_type_number, 6); + else if (lexer.contents() == PUGIXML_TEXT("mod")) + return binary_op_t(ast_op_mod, xpath_type_number, 6); + else + return binary_op_t(); + + case lex_equal: + return binary_op_t(ast_op_equal, xpath_type_boolean, 3); + + case lex_not_equal: + return binary_op_t(ast_op_not_equal, xpath_type_boolean, 3); + + case lex_less: + return binary_op_t(ast_op_less, xpath_type_boolean, 4); + + case lex_greater: + return binary_op_t(ast_op_greater, xpath_type_boolean, 4); + + case lex_less_or_equal: + return binary_op_t(ast_op_less_or_equal, xpath_type_boolean, 4); + + case lex_greater_or_equal: + return binary_op_t(ast_op_greater_or_equal, xpath_type_boolean, 4); + + case lex_plus: + return binary_op_t(ast_op_add, xpath_type_number, 5); + + case lex_minus: + return binary_op_t(ast_op_subtract, xpath_type_number, 5); + + case lex_multiply: + return binary_op_t(ast_op_multiply, xpath_type_number, 6); + + case lex_union: + return binary_op_t(ast_op_union, xpath_type_node_set, 7); + + default: + return binary_op_t(); + } + } + }; + + xpath_ast_node* parse_expression_rec(xpath_ast_node* lhs, int limit) + { + binary_op_t op = binary_op_t::parse(_lexer); + + while (op.asttype != ast_unknown && op.precedence >= limit) + { + _lexer.next(); + + xpath_ast_node* rhs = parse_path_or_unary_expression(); + + binary_op_t nextop = binary_op_t::parse(_lexer); + + while (nextop.asttype != ast_unknown && nextop.precedence > op.precedence) + { + rhs = parse_expression_rec(rhs, nextop.precedence); + + nextop = binary_op_t::parse(_lexer); + } + + if (op.asttype == ast_op_union && (lhs->rettype() != xpath_type_node_set || rhs->rettype() != xpath_type_node_set)) + throw_error("Union operator has to be applied to node sets"); + + lhs = new (alloc_node()) xpath_ast_node(op.asttype, op.rettype, lhs, rhs); + + op = binary_op_t::parse(_lexer); + } + + return lhs; + } + + // Expr ::= OrExpr + // OrExpr ::= AndExpr | OrExpr 'or' AndExpr + // AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr + // EqualityExpr ::= RelationalExpr + // | EqualityExpr '=' RelationalExpr + // | EqualityExpr '!=' RelationalExpr + // RelationalExpr ::= AdditiveExpr + // | RelationalExpr '<' AdditiveExpr + // | RelationalExpr '>' AdditiveExpr + // | RelationalExpr '<=' AdditiveExpr + // | RelationalExpr '>=' AdditiveExpr + // AdditiveExpr ::= MultiplicativeExpr + // | AdditiveExpr '+' MultiplicativeExpr + // | AdditiveExpr '-' MultiplicativeExpr + // MultiplicativeExpr ::= UnaryExpr + // | MultiplicativeExpr '*' UnaryExpr + // | MultiplicativeExpr 'div' UnaryExpr + // | MultiplicativeExpr 'mod' UnaryExpr + xpath_ast_node* parse_expression() + { + return parse_expression_rec(parse_path_or_unary_expression(), 0); + } + + xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result) + { + } + + xpath_ast_node* parse() + { + xpath_ast_node* result = parse_expression(); + + if (_lexer.current() != lex_eof) + { + // there are still unparsed tokens left, error + throw_error("Incorrect query"); + } + + return result; + } + + static xpath_ast_node* parse(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result) + { + xpath_parser parser(query, variables, alloc, result); + + #ifdef PUGIXML_NO_EXCEPTIONS + int error = setjmp(parser._error_handler); + + return (error == 0) ? parser.parse() : 0; + #else + return parser.parse(); + #endif + } + }; + + struct xpath_query_impl + { + static xpath_query_impl* create() + { + void* memory = xml_memory::allocate(sizeof(xpath_query_impl)); + + return new (memory) xpath_query_impl(); + } + + static void destroy(void* ptr) + { + if (!ptr) return; + + // free all allocated pages + static_cast(ptr)->alloc.release(); + + // free allocator memory (with the first page) + xml_memory::deallocate(ptr); + } + + xpath_query_impl(): root(0), alloc(&block) + { + block.next = 0; + block.capacity = sizeof(block.data); + } + + xpath_ast_node* root; + xpath_allocator alloc; + xpath_memory_block block; + }; + + PUGI__FN xpath_string evaluate_string_impl(xpath_query_impl* impl, const xpath_node& n, xpath_stack_data& sd) + { + if (!impl) return xpath_string(); + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return xpath_string(); + #endif + + xpath_context c(n, 1, 1); + + return impl->root->eval_string(c, sd.stack); + } + + PUGI__FN impl::xpath_ast_node* evaluate_node_set_prepare(xpath_query_impl* impl) + { + if (!impl) return 0; + + if (impl->root->rettype() != xpath_type_node_set) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return 0; + #else + xpath_parse_result res; + res.error = "Expression does not evaluate to node set"; + + throw xpath_exception(res); + #endif + } + + return impl->root; + } +PUGI__NS_END + +namespace pugi +{ +#ifndef PUGIXML_NO_EXCEPTIONS + PUGI__FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_) + { + assert(_result.error); + } + + PUGI__FN const char* xpath_exception::what() const throw() + { + return _result.error; + } + + PUGI__FN const xpath_parse_result& xpath_exception::result() const + { + return _result; + } +#endif + + PUGI__FN xpath_node::xpath_node() + { + } + + PUGI__FN xpath_node::xpath_node(const xml_node& node_): _node(node_) + { + } + + PUGI__FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_) + { + } + + PUGI__FN xml_node xpath_node::node() const + { + return _attribute ? xml_node() : _node; + } + + PUGI__FN xml_attribute xpath_node::attribute() const + { + return _attribute; + } + + PUGI__FN xml_node xpath_node::parent() const + { + return _attribute ? _node : _node.parent(); + } + + PUGI__FN static void unspecified_bool_xpath_node(xpath_node***) + { + } + + PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type() const + { + return (_node || _attribute) ? unspecified_bool_xpath_node : 0; + } + + PUGI__FN bool xpath_node::operator!() const + { + return !(_node || _attribute); + } + + PUGI__FN bool xpath_node::operator==(const xpath_node& n) const + { + return _node == n._node && _attribute == n._attribute; + } + + PUGI__FN bool xpath_node::operator!=(const xpath_node& n) const + { + return _node != n._node || _attribute != n._attribute; + } + +#ifdef __BORLANDC__ + PUGI__FN bool operator&&(const xpath_node& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + PUGI__FN bool operator||(const xpath_node& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_) + { + assert(begin_ <= end_); + + size_t size_ = static_cast(end_ - begin_); + + if (size_ <= 1) + { + // deallocate old buffer + if (_begin != &_storage) impl::xml_memory::deallocate(_begin); + + // use internal buffer + if (begin_ != end_) _storage = *begin_; + + _begin = &_storage; + _end = &_storage + size_; + } + else + { + // make heap copy + xpath_node* storage = static_cast(impl::xml_memory::allocate(size_ * sizeof(xpath_node))); + + if (!storage) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return; + #else + throw std::bad_alloc(); + #endif + } + + memcpy(storage, begin_, size_ * sizeof(xpath_node)); + + // deallocate old buffer + if (_begin != &_storage) impl::xml_memory::deallocate(_begin); + + // finalize + _begin = storage; + _end = storage + size_; + } + } + + PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage) + { + } + + PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_), _begin(&_storage), _end(&_storage) + { + _assign(begin_, end_); + } + + PUGI__FN xpath_node_set::~xpath_node_set() + { + if (_begin != &_storage) impl::xml_memory::deallocate(_begin); + } + + PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(ns._type), _begin(&_storage), _end(&_storage) + { + _assign(ns._begin, ns._end); + } + + PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) + { + if (this == &ns) return *this; + + _type = ns._type; + _assign(ns._begin, ns._end); + + return *this; + } + + PUGI__FN xpath_node_set::type_t xpath_node_set::type() const + { + return _type; + } + + PUGI__FN size_t xpath_node_set::size() const + { + return _end - _begin; + } + + PUGI__FN bool xpath_node_set::empty() const + { + return _begin == _end; + } + + PUGI__FN const xpath_node& xpath_node_set::operator[](size_t index) const + { + assert(index < size()); + return _begin[index]; + } + + PUGI__FN xpath_node_set::const_iterator xpath_node_set::begin() const + { + return _begin; + } + + PUGI__FN xpath_node_set::const_iterator xpath_node_set::end() const + { + return _end; + } + + PUGI__FN void xpath_node_set::sort(bool reverse) + { + _type = impl::xpath_sort(_begin, _end, _type, reverse); + } + + PUGI__FN xpath_node xpath_node_set::first() const + { + return impl::xpath_first(_begin, _end, _type); + } + + PUGI__FN xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0) + { + } + + PUGI__FN xpath_parse_result::operator bool() const + { + return error == 0; + } + + PUGI__FN const char* xpath_parse_result::description() const + { + return error ? error : "No error"; + } + + PUGI__FN xpath_variable::xpath_variable(): _type(xpath_type_none), _next(0) + { + } + + PUGI__FN const char_t* xpath_variable::name() const + { + switch (_type) + { + case xpath_type_node_set: + return static_cast(this)->name; + + case xpath_type_number: + return static_cast(this)->name; + + case xpath_type_string: + return static_cast(this)->name; + + case xpath_type_boolean: + return static_cast(this)->name; + + default: + assert(!"Invalid variable type"); + return 0; + } + } + + PUGI__FN xpath_value_type xpath_variable::type() const + { + return _type; + } + + PUGI__FN bool xpath_variable::get_boolean() const + { + return (_type == xpath_type_boolean) ? static_cast(this)->value : false; + } + + PUGI__FN double xpath_variable::get_number() const + { + return (_type == xpath_type_number) ? static_cast(this)->value : impl::gen_nan(); + } + + PUGI__FN const char_t* xpath_variable::get_string() const + { + const char_t* value = (_type == xpath_type_string) ? static_cast(this)->value : 0; + return value ? value : PUGIXML_TEXT(""); + } + + PUGI__FN const xpath_node_set& xpath_variable::get_node_set() const + { + return (_type == xpath_type_node_set) ? static_cast(this)->value : impl::dummy_node_set; + } + + PUGI__FN bool xpath_variable::set(bool value) + { + if (_type != xpath_type_boolean) return false; + + static_cast(this)->value = value; + return true; + } + + PUGI__FN bool xpath_variable::set(double value) + { + if (_type != xpath_type_number) return false; + + static_cast(this)->value = value; + return true; + } + + PUGI__FN bool xpath_variable::set(const char_t* value) + { + if (_type != xpath_type_string) return false; + + impl::xpath_variable_string* var = static_cast(this); + + // duplicate string + size_t size = (impl::strlength(value) + 1) * sizeof(char_t); + + char_t* copy = static_cast(impl::xml_memory::allocate(size)); + if (!copy) return false; + + memcpy(copy, value, size); + + // replace old string + if (var->value) impl::xml_memory::deallocate(var->value); + var->value = copy; + + return true; + } + + PUGI__FN bool xpath_variable::set(const xpath_node_set& value) + { + if (_type != xpath_type_node_set) return false; + + static_cast(this)->value = value; + return true; + } + + PUGI__FN xpath_variable_set::xpath_variable_set() + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) _data[i] = 0; + } + + PUGI__FN xpath_variable_set::~xpath_variable_set() + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + { + xpath_variable* var = _data[i]; + + while (var) + { + xpath_variable* next = var->_next; + + impl::delete_xpath_variable(var->_type, var); + + var = next; + } + } + } + + PUGI__FN xpath_variable* xpath_variable_set::find(const char_t* name) const + { + const size_t hash_size = sizeof(_data) / sizeof(_data[0]); + size_t hash = impl::hash_string(name) % hash_size; + + // look for existing variable + for (xpath_variable* var = _data[hash]; var; var = var->_next) + if (impl::strequal(var->name(), name)) + return var; + + return 0; + } + + PUGI__FN xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type) + { + const size_t hash_size = sizeof(_data) / sizeof(_data[0]); + size_t hash = impl::hash_string(name) % hash_size; + + // look for existing variable + for (xpath_variable* var = _data[hash]; var; var = var->_next) + if (impl::strequal(var->name(), name)) + return var->type() == type ? var : 0; + + // add new variable + xpath_variable* result = impl::new_xpath_variable(type, name); + + if (result) + { + result->_type = type; + result->_next = _data[hash]; + + _data[hash] = result; + } + + return result; + } + + PUGI__FN bool xpath_variable_set::set(const char_t* name, bool value) + { + xpath_variable* var = add(name, xpath_type_boolean); + return var ? var->set(value) : false; + } + + PUGI__FN bool xpath_variable_set::set(const char_t* name, double value) + { + xpath_variable* var = add(name, xpath_type_number); + return var ? var->set(value) : false; + } + + PUGI__FN bool xpath_variable_set::set(const char_t* name, const char_t* value) + { + xpath_variable* var = add(name, xpath_type_string); + return var ? var->set(value) : false; + } + + PUGI__FN bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value) + { + xpath_variable* var = add(name, xpath_type_node_set); + return var ? var->set(value) : false; + } + + PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name) + { + return find(name); + } + + PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const + { + return find(name); + } + + PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) + { + impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create(); + + if (!qimpl) + { + #ifdef PUGIXML_NO_EXCEPTIONS + _result.error = "Out of memory"; + #else + throw std::bad_alloc(); + #endif + } + else + { + impl::buffer_holder impl_holder(qimpl, impl::xpath_query_impl::destroy); + + qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &_result); + + if (qimpl->root) + { + qimpl->root->optimize(&qimpl->alloc); + + _impl = static_cast(impl_holder.release()); + _result.error = 0; + } + } + } + + PUGI__FN xpath_query::~xpath_query() + { + impl::xpath_query_impl::destroy(_impl); + } + + PUGI__FN xpath_value_type xpath_query::return_type() const + { + if (!_impl) return xpath_type_none; + + return static_cast(_impl)->root->rettype(); + } + + PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const + { + if (!_impl) return false; + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return false; + #endif + + return static_cast(_impl)->root->eval_boolean(c, sd.stack); + } + + PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const + { + if (!_impl) return impl::gen_nan(); + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return impl::gen_nan(); + #endif + + return static_cast(_impl)->root->eval_number(c, sd.stack); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN string_t xpath_query::evaluate_string(const xpath_node& n) const + { + impl::xpath_stack_data sd; + + impl::xpath_string r = impl::evaluate_string_impl(static_cast(_impl), n, sd); + + return string_t(r.c_str(), r.length()); + } +#endif + + PUGI__FN size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const + { + impl::xpath_stack_data sd; + + impl::xpath_string r = impl::evaluate_string_impl(static_cast(_impl), n, sd); + + size_t full_size = r.length() + 1; + + if (capacity > 0) + { + size_t size = (full_size < capacity) ? full_size : capacity; + assert(size > 0); + + memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t)); + buffer[size - 1] = 0; + } + + return full_size; + } + + PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const + { + impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast(_impl)); + if (!root) return xpath_node_set(); + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return xpath_node_set(); + #endif + + impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_all); + + return xpath_node_set(r.begin(), r.end(), r.type()); + } + + PUGI__FN xpath_node xpath_query::evaluate_node(const xpath_node& n) const + { + impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast(_impl)); + if (!root) return xpath_node(); + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return xpath_node(); + #endif + + impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_first); + + return r.first(); + } + + PUGI__FN const xpath_parse_result& xpath_query::result() const + { + return _result; + } + + PUGI__FN static void unspecified_bool_xpath_query(xpath_query***) + { + } + + PUGI__FN xpath_query::operator xpath_query::unspecified_bool_type() const + { + return _impl ? unspecified_bool_xpath_query : 0; + } + + PUGI__FN bool xpath_query::operator!() const + { + return !_impl; + } + + PUGI__FN xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables) const + { + xpath_query q(query, variables); + return select_node(q); + } + + PUGI__FN xpath_node xml_node::select_node(const xpath_query& query) const + { + return query.evaluate_node(*this); + } + + PUGI__FN xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const + { + xpath_query q(query, variables); + return select_nodes(q); + } + + PUGI__FN xpath_node_set xml_node::select_nodes(const xpath_query& query) const + { + return query.evaluate_node_set(*this); + } + + PUGI__FN xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const + { + xpath_query q(query, variables); + return select_single_node(q); + } + + PUGI__FN xpath_node xml_node::select_single_node(const xpath_query& query) const + { + return query.evaluate_node(*this); + } +} + +#endif + +#ifdef __BORLANDC__ +# pragma option pop +#endif + +// Intel C++ does not properly keep warning state for function templates, +// so popping warning state at the end of translation unit leads to warnings in the middle. +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +# pragma warning(pop) +#endif + +// Undefine all local macros (makes sure we're not leaking macros in header-only mode) +#undef PUGI__NO_INLINE +#undef PUGI__UNLIKELY +#undef PUGI__STATIC_ASSERT +#undef PUGI__DMC_VOLATILE +#undef PUGI__MSVC_CRT_VERSION +#undef PUGI__NS_BEGIN +#undef PUGI__NS_END +#undef PUGI__FN +#undef PUGI__FN_NO_INLINE +#undef PUGI__NODETYPE +#undef PUGI__IS_CHARTYPE_IMPL +#undef PUGI__IS_CHARTYPE +#undef PUGI__IS_CHARTYPEX +#undef PUGI__ENDSWITH +#undef PUGI__SKIPWS +#undef PUGI__OPTSET +#undef PUGI__PUSHNODE +#undef PUGI__POPNODE +#undef PUGI__SCANFOR +#undef PUGI__SCANWHILE +#undef PUGI__SCANWHILE_UNROLL +#undef PUGI__ENDSEG +#undef PUGI__THROW_ERROR +#undef PUGI__CHECK_ERROR + +#endif + +/** + * Copyright (c) 2006-2014 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma GCC diagnostic pop diff --git a/src/pugixml/pugixml.hpp b/src/pugixml/pugixml.hpp new file mode 100644 index 0000000..d4d5a62 --- /dev/null +++ b/src/pugixml/pugixml.hpp @@ -0,0 +1,1366 @@ +/** + * pugixml parser - version 1.5 + * -------------------------------------------------------- + * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at http://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef PUGIXML_VERSION +// Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons +# define PUGIXML_VERSION 150 +#endif + +// Include user configuration file (this can define various configuration macros) +#include "pugiconfig.hpp" + +#ifndef HEADER_PUGIXML_HPP +#define HEADER_PUGIXML_HPP + +// Include stddef.h for size_t and ptrdiff_t +#include + +// Include exception header for XPath +#if !defined(PUGIXML_NO_XPATH) && !defined(PUGIXML_NO_EXCEPTIONS) +# include +#endif + +// Include STL headers +#ifndef PUGIXML_NO_STL +# include +# include +# include +#endif + +// Macro for deprecated features +#ifndef PUGIXML_DEPRECATED +# if defined(__GNUC__) +# define PUGIXML_DEPRECATED __attribute__((deprecated)) +# elif defined(_MSC_VER) && _MSC_VER >= 1300 +# define PUGIXML_DEPRECATED __declspec(deprecated) +# else +# define PUGIXML_DEPRECATED +# endif +#endif + +// If no API is defined, assume default +#ifndef PUGIXML_API +# define PUGIXML_API +#endif + +// If no API for classes is defined, assume default +#ifndef PUGIXML_CLASS +# define PUGIXML_CLASS PUGIXML_API +#endif + +// If no API for functions is defined, assume default +#ifndef PUGIXML_FUNCTION +# define PUGIXML_FUNCTION PUGIXML_API +#endif + +// If the platform is known to have long long support, enable long long functions +#ifndef PUGIXML_HAS_LONG_LONG +# if defined(__cplusplus) && __cplusplus >= 201103 +# define PUGIXML_HAS_LONG_LONG +# elif defined(_MSC_VER) && _MSC_VER >= 1400 +# define PUGIXML_HAS_LONG_LONG +# endif +#endif + +// Character interface macros +#ifdef PUGIXML_WCHAR_MODE +# define PUGIXML_TEXT(t) L ## t +# define PUGIXML_CHAR wchar_t +#else +# define PUGIXML_TEXT(t) t +# define PUGIXML_CHAR char +#endif + +namespace pugi +{ + // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE + typedef PUGIXML_CHAR char_t; + +#ifndef PUGIXML_NO_STL + // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE + typedef std::basic_string, std::allocator > string_t; +#endif +} + +// The PugiXML namespace +namespace pugi +{ + // Tree node types + enum xml_node_type + { + node_null, // Empty (null) node handle + node_document, // A document tree's absolute root + node_element, // Element tag, i.e. '' + node_pcdata, // Plain character data, i.e. 'text' + node_cdata, // Character data, i.e. '' + node_comment, // Comment tag, i.e. '' + node_pi, // Processing instruction, i.e. '' + node_declaration, // Document declaration, i.e. '' + node_doctype // Document type declaration, i.e. '' + }; + + // Parsing options + + // Minimal parsing mode (equivalent to turning all other flags off). + // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed. + const unsigned int parse_minimal = 0x0000; + + // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default. + const unsigned int parse_pi = 0x0001; + + // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default. + const unsigned int parse_comments = 0x0002; + + // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default. + const unsigned int parse_cdata = 0x0004; + + // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree. + // This flag is off by default; turning it on usually results in slower parsing and more memory consumption. + const unsigned int parse_ws_pcdata = 0x0008; + + // This flag determines if character and entity references are expanded during parsing. This flag is on by default. + const unsigned int parse_escapes = 0x0010; + + // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default. + const unsigned int parse_eol = 0x0020; + + // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default. + const unsigned int parse_wconv_attribute = 0x0040; + + // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default. + const unsigned int parse_wnorm_attribute = 0x0080; + + // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default. + const unsigned int parse_declaration = 0x0100; + + // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default. + const unsigned int parse_doctype = 0x0200; + + // This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only + // of whitespace is added to the DOM tree. + // This flag is off by default; turning it on may result in slower parsing and more memory consumption. + const unsigned int parse_ws_pcdata_single = 0x0400; + + // This flag determines if leading and trailing whitespace is to be removed from plain character data. This flag is off by default. + const unsigned int parse_trim_pcdata = 0x0800; + + // This flag determines if plain character data that does not have a parent node is added to the DOM tree, and if an empty document + // is a valid document. This flag is off by default. + const unsigned int parse_fragment = 0x1000; + + // The default parsing mode. + // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, + // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. + const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol; + + // The full parsing mode. + // Nodes of all types are added to the DOM tree, character/reference entities are expanded, + // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. + const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype; + + // These flags determine the encoding of input data for XML document + enum xml_encoding + { + encoding_auto, // Auto-detect input encoding using BOM or < / class xml_object_range + { + public: + typedef It const_iterator; + typedef It iterator; + + xml_object_range(It b, It e): _begin(b), _end(e) + { + } + + It begin() const { return _begin; } + It end() const { return _end; } + + private: + It _begin, _end; + }; + + // Writer interface for node printing (see xml_node::print) + class PUGIXML_CLASS xml_writer + { + public: + virtual ~xml_writer() {} + + // Write memory chunk into stream/file/whatever + virtual void write(const void* data, size_t size) = 0; + }; + + // xml_writer implementation for FILE* + class PUGIXML_CLASS xml_writer_file: public xml_writer + { + public: + // Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio + xml_writer_file(void* file); + + virtual void write(const void* data, size_t size); + + private: + void* file; + }; + + #ifndef PUGIXML_NO_STL + // xml_writer implementation for streams + class PUGIXML_CLASS xml_writer_stream: public xml_writer + { + public: + // Construct writer from an output stream object + xml_writer_stream(std::basic_ostream >& stream); + xml_writer_stream(std::basic_ostream >& stream); + + virtual void write(const void* data, size_t size); + + private: + std::basic_ostream >* narrow_stream; + std::basic_ostream >* wide_stream; + }; + #endif + + // A light-weight handle for manipulating attributes in DOM tree + class PUGIXML_CLASS xml_attribute + { + friend class xml_attribute_iterator; + friend class xml_node; + + private: + xml_attribute_struct* _attr; + + typedef void (*unspecified_bool_type)(xml_attribute***); + + public: + // Default constructor. Constructs an empty attribute. + xml_attribute(); + + // Constructs attribute from internal pointer + explicit xml_attribute(xml_attribute_struct* attr); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators (compares wrapped attribute pointers) + bool operator==(const xml_attribute& r) const; + bool operator!=(const xml_attribute& r) const; + bool operator<(const xml_attribute& r) const; + bool operator>(const xml_attribute& r) const; + bool operator<=(const xml_attribute& r) const; + bool operator>=(const xml_attribute& r) const; + + // Check if attribute is empty + bool empty() const; + + // Get attribute name/value, or "" if attribute is empty + const char_t* name() const; + const char_t* value() const; + + // Get attribute value, or the default value if attribute is empty + const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; + + // Get attribute value as a number, or the default value if conversion did not succeed or attribute is empty + int as_int(int def = 0) const; + unsigned int as_uint(unsigned int def = 0) const; + double as_double(double def = 0) const; + float as_float(float def = 0) const; + + #ifdef PUGIXML_HAS_LONG_LONG + long long as_llong(long long def = 0) const; + unsigned long long as_ullong(unsigned long long def = 0) const; + #endif + + // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty + bool as_bool(bool def = false) const; + + // Set attribute name/value (returns false if attribute is empty or there is not enough memory) + bool set_name(const char_t* rhs); + bool set_value(const char_t* rhs); + + // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") + bool set_value(int rhs); + bool set_value(unsigned int rhs); + bool set_value(double rhs); + bool set_value(float rhs); + bool set_value(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + bool set_value(long long rhs); + bool set_value(unsigned long long rhs); + #endif + + // Set attribute value (equivalent to set_value without error checking) + xml_attribute& operator=(const char_t* rhs); + xml_attribute& operator=(int rhs); + xml_attribute& operator=(unsigned int rhs); + xml_attribute& operator=(double rhs); + xml_attribute& operator=(float rhs); + xml_attribute& operator=(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + xml_attribute& operator=(long long rhs); + xml_attribute& operator=(unsigned long long rhs); + #endif + + // Get next/previous attribute in the attribute list of the parent node + xml_attribute next_attribute() const; + xml_attribute previous_attribute() const; + + // Get hash value (unique for handles to the same object) + size_t hash_value() const; + + // Get internal pointer + xml_attribute_struct* internal_object() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs); +#endif + + // A light-weight handle for manipulating nodes in DOM tree + class PUGIXML_CLASS xml_node + { + friend class xml_attribute_iterator; + friend class xml_node_iterator; + friend class xml_named_node_iterator; + + protected: + xml_node_struct* _root; + + typedef void (*unspecified_bool_type)(xml_node***); + + public: + // Default constructor. Constructs an empty node. + xml_node(); + + // Constructs node from internal pointer + explicit xml_node(xml_node_struct* p); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators (compares wrapped node pointers) + bool operator==(const xml_node& r) const; + bool operator!=(const xml_node& r) const; + bool operator<(const xml_node& r) const; + bool operator>(const xml_node& r) const; + bool operator<=(const xml_node& r) const; + bool operator>=(const xml_node& r) const; + + // Check if node is empty. + bool empty() const; + + // Get node type + xml_node_type type() const; + + // Get node name, or "" if node is empty or it has no name + const char_t* name() const; + + // Get node value, or "" if node is empty or it has no value + // Note: For text node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes. + const char_t* value() const; + + // Get attribute list + xml_attribute first_attribute() const; + xml_attribute last_attribute() const; + + // Get children list + xml_node first_child() const; + xml_node last_child() const; + + // Get next/previous sibling in the children list of the parent node + xml_node next_sibling() const; + xml_node previous_sibling() const; + + // Get parent node + xml_node parent() const; + + // Get root of DOM tree this node belongs to + xml_node root() const; + + // Get text object for the current node + xml_text text() const; + + // Get child, attribute or next/previous sibling with the specified name + xml_node child(const char_t* name) const; + xml_attribute attribute(const char_t* name) const; + xml_node next_sibling(const char_t* name) const; + xml_node previous_sibling(const char_t* name) const; + + // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA + const char_t* child_value() const; + + // Get child value of child with specified name. Equivalent to child(name).child_value(). + const char_t* child_value(const char_t* name) const; + + // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) + bool set_name(const char_t* rhs); + bool set_value(const char_t* rhs); + + // Add attribute with specified name. Returns added attribute, or empty attribute on errors. + xml_attribute append_attribute(const char_t* name); + xml_attribute prepend_attribute(const char_t* name); + xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); + xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); + + // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. + xml_attribute append_copy(const xml_attribute& proto); + xml_attribute prepend_copy(const xml_attribute& proto); + xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr); + xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr); + + // Add child node with specified type. Returns added node, or empty node on errors. + xml_node append_child(xml_node_type type = node_element); + xml_node prepend_child(xml_node_type type = node_element); + xml_node insert_child_after(xml_node_type type, const xml_node& node); + xml_node insert_child_before(xml_node_type type, const xml_node& node); + + // Add child element with specified name. Returns added node, or empty node on errors. + xml_node append_child(const char_t* name); + xml_node prepend_child(const char_t* name); + xml_node insert_child_after(const char_t* name, const xml_node& node); + xml_node insert_child_before(const char_t* name, const xml_node& node); + + // Add a copy of the specified node as a child. Returns added node, or empty node on errors. + xml_node append_copy(const xml_node& proto); + xml_node prepend_copy(const xml_node& proto); + xml_node insert_copy_after(const xml_node& proto, const xml_node& node); + xml_node insert_copy_before(const xml_node& proto, const xml_node& node); + + // Move the specified node to become a child of this node. Returns moved node, or empty node on errors. + xml_node append_move(const xml_node& moved); + xml_node prepend_move(const xml_node& moved); + xml_node insert_move_after(const xml_node& moved, const xml_node& node); + xml_node insert_move_before(const xml_node& moved, const xml_node& node); + + // Remove specified attribute + bool remove_attribute(const xml_attribute& a); + bool remove_attribute(const char_t* name); + + // Remove specified child + bool remove_child(const xml_node& n); + bool remove_child(const char_t* name); + + // Parses buffer as an XML document fragment and appends all nodes as children of the current node. + // Copies/converts the buffer, so it may be deleted or changed after the function returns. + // Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory. + xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Find attribute using predicate. Returns first attribute for which predicate returned true. + template xml_attribute find_attribute(Predicate pred) const + { + if (!_root) return xml_attribute(); + + for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute()) + if (pred(attrib)) + return attrib; + + return xml_attribute(); + } + + // Find child node using predicate. Returns first child for which predicate returned true. + template xml_node find_child(Predicate pred) const + { + if (!_root) return xml_node(); + + for (xml_node node = first_child(); node; node = node.next_sibling()) + if (pred(node)) + return node; + + return xml_node(); + } + + // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true. + template xml_node find_node(Predicate pred) const + { + if (!_root) return xml_node(); + + xml_node cur = first_child(); + + while (cur._root && cur._root != _root) + { + if (pred(cur)) return cur; + + if (cur.first_child()) cur = cur.first_child(); + else if (cur.next_sibling()) cur = cur.next_sibling(); + else + { + while (!cur.next_sibling() && cur._root != _root) cur = cur.parent(); + + if (cur._root != _root) cur = cur.next_sibling(); + } + } + + return xml_node(); + } + + // Find child node by attribute name/value + xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const; + xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const; + + #ifndef PUGIXML_NO_STL + // Get the absolute node path from root as a text string. + string_t path(char_t delimiter = '/') const; + #endif + + // Search for a node by path consisting of node names and . or .. elements. + xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const; + + // Recursively traverse subtree with xml_tree_walker + bool traverse(xml_tree_walker& walker); + + #ifndef PUGIXML_NO_XPATH + // Select single node by evaluating XPath query. Returns first node from the resulting node set. + xpath_node select_node(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node select_node(const xpath_query& query) const; + + // Select node set by evaluating XPath query + xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node_set select_nodes(const xpath_query& query) const; + + // (deprecated: use select_node instead) Select single node by evaluating XPath query. + xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node select_single_node(const xpath_query& query) const; + + #endif + + // Print subtree using a writer object + void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + + #ifndef PUGIXML_NO_STL + // Print subtree to stream + void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; + #endif + + // Child nodes iterators + typedef xml_node_iterator iterator; + + iterator begin() const; + iterator end() const; + + // Attribute iterators + typedef xml_attribute_iterator attribute_iterator; + + attribute_iterator attributes_begin() const; + attribute_iterator attributes_end() const; + + // Range-based for support + xml_object_range children() const; + xml_object_range children(const char_t* name) const; + xml_object_range attributes() const; + + // Get node offset in parsed file/string (in char_t units) for debugging purposes + ptrdiff_t offset_debug() const; + + // Get hash value (unique for handles to the same object) + size_t hash_value() const; + + // Get internal pointer + xml_node_struct* internal_object() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs); +#endif + + // A helper for working with text inside PCDATA nodes + class PUGIXML_CLASS xml_text + { + friend class xml_node; + + xml_node_struct* _root; + + typedef void (*unspecified_bool_type)(xml_text***); + + explicit xml_text(xml_node_struct* root); + + xml_node_struct* _data_new(); + xml_node_struct* _data() const; + + public: + // Default constructor. Constructs an empty object. + xml_text(); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Check if text object is empty + bool empty() const; + + // Get text, or "" if object is empty + const char_t* get() const; + + // Get text, or the default value if object is empty + const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; + + // Get text as a number, or the default value if conversion did not succeed or object is empty + int as_int(int def = 0) const; + unsigned int as_uint(unsigned int def = 0) const; + double as_double(double def = 0) const; + float as_float(float def = 0) const; + + #ifdef PUGIXML_HAS_LONG_LONG + long long as_llong(long long def = 0) const; + unsigned long long as_ullong(unsigned long long def = 0) const; + #endif + + // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty + bool as_bool(bool def = false) const; + + // Set text (returns false if object is empty or there is not enough memory) + bool set(const char_t* rhs); + + // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") + bool set(int rhs); + bool set(unsigned int rhs); + bool set(double rhs); + bool set(float rhs); + bool set(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + bool set(long long rhs); + bool set(unsigned long long rhs); + #endif + + // Set text (equivalent to set without error checking) + xml_text& operator=(const char_t* rhs); + xml_text& operator=(int rhs); + xml_text& operator=(unsigned int rhs); + xml_text& operator=(double rhs); + xml_text& operator=(float rhs); + xml_text& operator=(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + xml_text& operator=(long long rhs); + xml_text& operator=(unsigned long long rhs); + #endif + + // Get the data node (node_pcdata or node_cdata) for this object + xml_node data() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_text& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_text& lhs, bool rhs); +#endif + + // Child node iterator (a bidirectional iterator over a collection of xml_node) + class PUGIXML_CLASS xml_node_iterator + { + friend class xml_node; + + private: + mutable xml_node _wrap; + xml_node _parent; + + xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent); + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_node value_type; + typedef xml_node* pointer; + typedef xml_node& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_node_iterator(); + + // Construct an iterator which points to the specified node + xml_node_iterator(const xml_node& node); + + // Iterator operators + bool operator==(const xml_node_iterator& rhs) const; + bool operator!=(const xml_node_iterator& rhs) const; + + xml_node& operator*() const; + xml_node* operator->() const; + + const xml_node_iterator& operator++(); + xml_node_iterator operator++(int); + + const xml_node_iterator& operator--(); + xml_node_iterator operator--(int); + }; + + // Attribute iterator (a bidirectional iterator over a collection of xml_attribute) + class PUGIXML_CLASS xml_attribute_iterator + { + friend class xml_node; + + private: + mutable xml_attribute _wrap; + xml_node _parent; + + xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent); + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_attribute value_type; + typedef xml_attribute* pointer; + typedef xml_attribute& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_attribute_iterator(); + + // Construct an iterator which points to the specified attribute + xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent); + + // Iterator operators + bool operator==(const xml_attribute_iterator& rhs) const; + bool operator!=(const xml_attribute_iterator& rhs) const; + + xml_attribute& operator*() const; + xml_attribute* operator->() const; + + const xml_attribute_iterator& operator++(); + xml_attribute_iterator operator++(int); + + const xml_attribute_iterator& operator--(); + xml_attribute_iterator operator--(int); + }; + + // Named node range helper + class PUGIXML_CLASS xml_named_node_iterator + { + friend class xml_node; + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_node value_type; + typedef xml_node* pointer; + typedef xml_node& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_named_node_iterator(); + + // Construct an iterator which points to the specified node + xml_named_node_iterator(const xml_node& node, const char_t* name); + + // Iterator operators + bool operator==(const xml_named_node_iterator& rhs) const; + bool operator!=(const xml_named_node_iterator& rhs) const; + + xml_node& operator*() const; + xml_node* operator->() const; + + const xml_named_node_iterator& operator++(); + xml_named_node_iterator operator++(int); + + const xml_named_node_iterator& operator--(); + xml_named_node_iterator operator--(int); + + private: + mutable xml_node _wrap; + xml_node _parent; + const char_t* _name; + + xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name); + }; + + // Abstract tree walker class (see xml_node::traverse) + class PUGIXML_CLASS xml_tree_walker + { + friend class xml_node; + + private: + int _depth; + + protected: + // Get current traversal depth + int depth() const; + + public: + xml_tree_walker(); + virtual ~xml_tree_walker(); + + // Callback that is called when traversal begins + virtual bool begin(xml_node& node); + + // Callback that is called for each node traversed + virtual bool for_each(xml_node& node) = 0; + + // Callback that is called when traversal ends + virtual bool end(xml_node& node); + }; + + // Parsing status, returned as part of xml_parse_result object + enum xml_parse_status + { + status_ok = 0, // No error + + status_file_not_found, // File was not found during load_file() + status_io_error, // Error reading from file/stream + status_out_of_memory, // Could not allocate memory + status_internal_error, // Internal error occurred + + status_unrecognized_tag, // Parser could not determine tag type + + status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction + status_bad_comment, // Parsing error occurred while parsing comment + status_bad_cdata, // Parsing error occurred while parsing CDATA section + status_bad_doctype, // Parsing error occurred while parsing document type declaration + status_bad_pcdata, // Parsing error occurred while parsing PCDATA section + status_bad_start_element, // Parsing error occurred while parsing start element tag + status_bad_attribute, // Parsing error occurred while parsing element attribute + status_bad_end_element, // Parsing error occurred while parsing end element tag + status_end_element_mismatch,// There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag) + + status_append_invalid_root, // Unable to append nodes since root type is not node_element or node_document (exclusive to xml_node::append_buffer) + + status_no_document_element // Parsing resulted in a document without element nodes + }; + + // Parsing result + struct PUGIXML_CLASS xml_parse_result + { + // Parsing status (see xml_parse_status) + xml_parse_status status; + + // Last parsed offset (in char_t units from start of input data) + ptrdiff_t offset; + + // Source document encoding + xml_encoding encoding; + + // Default constructor, initializes object to failed state + xml_parse_result(); + + // Cast to bool operator + operator bool() const; + + // Get error description + const char* description() const; + }; + + // Document class (DOM tree root) + class PUGIXML_CLASS xml_document: public xml_node + { + private: + char_t* _buffer; + + char _memory[192]; + + // Non-copyable semantics + xml_document(const xml_document&); + const xml_document& operator=(const xml_document&); + + void create(); + void destroy(); + + public: + // Default constructor, makes empty document + xml_document(); + + // Destructor, invalidates all node/attribute handles to this document + ~xml_document(); + + // Removes all nodes, leaving the empty document + void reset(); + + // Removes all nodes, then copies the entire contents of the specified document + void reset(const xml_document& proto); + + #ifndef PUGIXML_NO_STL + // Load document from stream. + xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); + #endif + + // (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied. + xml_parse_result load(const char_t* contents, unsigned int options = parse_default); + + // Load document from zero-terminated string. No encoding conversions are applied. + xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default); + + // Load document from file + xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns. + xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). + // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed. + xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). + // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore). + xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details). + void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + + #ifndef PUGIXML_NO_STL + // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). + void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; + #endif + + // Save XML to file + bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + + // Get document element + xml_node document_element() const; + }; + +#ifndef PUGIXML_NO_XPATH + // XPath query return type + enum xpath_value_type + { + xpath_type_none, // Unknown type (query failed to compile) + xpath_type_node_set, // Node set (xpath_node_set) + xpath_type_number, // Number + xpath_type_string, // String + xpath_type_boolean // Boolean + }; + + // XPath parsing result + struct PUGIXML_CLASS xpath_parse_result + { + // Error message (0 if no error) + const char* error; + + // Last parsed offset (in char_t units from string start) + ptrdiff_t offset; + + // Default constructor, initializes object to failed state + xpath_parse_result(); + + // Cast to bool operator + operator bool() const; + + // Get error description + const char* description() const; + }; + + // A single XPath variable + class PUGIXML_CLASS xpath_variable + { + friend class xpath_variable_set; + + protected: + xpath_value_type _type; + xpath_variable* _next; + + xpath_variable(); + + // Non-copyable semantics + xpath_variable(const xpath_variable&); + xpath_variable& operator=(const xpath_variable&); + + public: + // Get variable name + const char_t* name() const; + + // Get variable type + xpath_value_type type() const; + + // Get variable value; no type conversion is performed, default value (false, NaN, empty string, empty node set) is returned on type mismatch error + bool get_boolean() const; + double get_number() const; + const char_t* get_string() const; + const xpath_node_set& get_node_set() const; + + // Set variable value; no type conversion is performed, false is returned on type mismatch error + bool set(bool value); + bool set(double value); + bool set(const char_t* value); + bool set(const xpath_node_set& value); + }; + + // A set of XPath variables + class PUGIXML_CLASS xpath_variable_set + { + private: + xpath_variable* _data[64]; + + // Non-copyable semantics + xpath_variable_set(const xpath_variable_set&); + xpath_variable_set& operator=(const xpath_variable_set&); + + xpath_variable* find(const char_t* name) const; + + public: + // Default constructor/destructor + xpath_variable_set(); + ~xpath_variable_set(); + + // Add a new variable or get the existing one, if the types match + xpath_variable* add(const char_t* name, xpath_value_type type); + + // Set value of an existing variable; no type conversion is performed, false is returned if there is no such variable or if types mismatch + bool set(const char_t* name, bool value); + bool set(const char_t* name, double value); + bool set(const char_t* name, const char_t* value); + bool set(const char_t* name, const xpath_node_set& value); + + // Get existing variable by name + xpath_variable* get(const char_t* name); + const xpath_variable* get(const char_t* name) const; + }; + + // A compiled XPath query object + class PUGIXML_CLASS xpath_query + { + private: + void* _impl; + xpath_parse_result _result; + + typedef void (*unspecified_bool_type)(xpath_query***); + + // Non-copyable semantics + xpath_query(const xpath_query&); + xpath_query& operator=(const xpath_query&); + + public: + // Construct a compiled object from XPath expression. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. + explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0); + + // Destructor + ~xpath_query(); + + // Get query expression return type + xpath_value_type return_type() const; + + // Evaluate expression as boolean value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + bool evaluate_boolean(const xpath_node& n) const; + + // Evaluate expression as double value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + double evaluate_number(const xpath_node& n) const; + + #ifndef PUGIXML_NO_STL + // Evaluate expression as string value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + string_t evaluate_string(const xpath_node& n) const; + #endif + + // Evaluate expression as string value in the specified context; performs type conversion if necessary. + // At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero). + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead. + size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const; + + // Evaluate expression as node set in the specified context. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node set instead. + xpath_node_set evaluate_node_set(const xpath_node& n) const; + + // Evaluate expression as node set in the specified context. + // Return first node in document order, or empty node if node set is empty. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node instead. + xpath_node evaluate_node(const xpath_node& n) const; + + // Get parsing result (used to get compilation errors in PUGIXML_NO_EXCEPTIONS mode) + const xpath_parse_result& result() const; + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + }; + + #ifndef PUGIXML_NO_EXCEPTIONS + // XPath exception class + class PUGIXML_CLASS xpath_exception: public std::exception + { + private: + xpath_parse_result _result; + + public: + // Construct exception from parse result + explicit xpath_exception(const xpath_parse_result& result); + + // Get error message + virtual const char* what() const throw(); + + // Get parse result + const xpath_parse_result& result() const; + }; + #endif + + // XPath node class (either xml_node or xml_attribute) + class PUGIXML_CLASS xpath_node + { + private: + xml_node _node; + xml_attribute _attribute; + + typedef void (*unspecified_bool_type)(xpath_node***); + + public: + // Default constructor; constructs empty XPath node + xpath_node(); + + // Construct XPath node from XML node/attribute + xpath_node(const xml_node& node); + xpath_node(const xml_attribute& attribute, const xml_node& parent); + + // Get node/attribute, if any + xml_node node() const; + xml_attribute attribute() const; + + // Get parent of contained node/attribute + xml_node parent() const; + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators + bool operator==(const xpath_node& n) const; + bool operator!=(const xpath_node& n) const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xpath_node& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xpath_node& lhs, bool rhs); +#endif + + // A fixed-size collection of XPath nodes + class PUGIXML_CLASS xpath_node_set + { + public: + // Collection type + enum type_t + { + type_unsorted, // Not ordered + type_sorted, // Sorted by document order (ascending) + type_sorted_reverse // Sorted by document order (descending) + }; + + // Constant iterator type + typedef const xpath_node* const_iterator; + + // We define non-constant iterator to be the same as constant iterator so that various generic algorithms (i.e. boost foreach) work + typedef const xpath_node* iterator; + + // Default constructor. Constructs empty set. + xpath_node_set(); + + // Constructs a set from iterator range; data is not checked for duplicates and is not sorted according to provided type, so be careful + xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted); + + // Destructor + ~xpath_node_set(); + + // Copy constructor/assignment operator + xpath_node_set(const xpath_node_set& ns); + xpath_node_set& operator=(const xpath_node_set& ns); + + // Get collection type + type_t type() const; + + // Get collection size + size_t size() const; + + // Indexing operator + const xpath_node& operator[](size_t index) const; + + // Collection iterators + const_iterator begin() const; + const_iterator end() const; + + // Sort the collection in ascending/descending order by document order + void sort(bool reverse = false); + + // Get first node in the collection by document order + xpath_node first() const; + + // Check if collection is empty + bool empty() const; + + private: + type_t _type; + + xpath_node _storage; + + xpath_node* _begin; + xpath_node* _end; + + void _assign(const_iterator begin, const_iterator end); + }; +#endif + +#ifndef PUGIXML_NO_STL + // Convert wide string to UTF8 + std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); + std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); + + // Convert UTF8 to wide string + std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); + std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); +#endif + + // Memory allocation function interface; returns pointer to allocated memory or NULL on failure + typedef void* (*allocation_function)(size_t size); + + // Memory deallocation function interface + typedef void (*deallocation_function)(void* ptr); + + // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions. + void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate); + + // Get current memory management functions + allocation_function PUGIXML_FUNCTION get_memory_allocation_function(); + deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function(); +} + +#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) +namespace std +{ + // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&); +} +#endif + +#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) +namespace std +{ + // Workarounds for (non-standard) iterator category detection + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&); +} +#endif + +#endif + +// Make sure implementation is included in header-only mode +// Use macro expansion in #include to work around QMake (QTBUG-11923) +#if defined(PUGIXML_HEADER_ONLY) && !defined(PUGIXML_SOURCE) +# define PUGIXML_SOURCE "pugixml.cpp" +# include PUGIXML_SOURCE +#endif + +/** + * Copyright (c) 2006-2014 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/src/vcf/VcfFile.cpp b/src/vcf/VcfFile.cpp new file mode 100644 index 0000000..b2fd2d4 --- /dev/null +++ b/src/vcf/VcfFile.cpp @@ -0,0 +1,34 @@ +#include "PbbamInternalConfig.h" + +#include "pbbam/vcf/VcfFile.h" + +#include +#include + +#include "pbbam/vcf/VcfFormat.h" + +namespace PacBio { +namespace VCF { + +static_assert(std::is_copy_constructible::value, + "VcfFile(const VcfFile&) is not = default"); +static_assert(std::is_copy_assignable::value, + "VcfFile& operator=(const VcfFile&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "VcfFile(VcfFile&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +VcfFile::VcfFile(std::string fn) + : filename_{std::move(fn)}, header_{VcfFormat::HeaderFromFile(filename_)} +{ +} + +const std::string& VcfFile::Filename() const { return filename_; } + +const VcfHeader& VcfFile::Header() const { return header_; } + +} // namespace VCF +} // namespace PacBio diff --git a/src/vcf/VcfFormat.cpp b/src/vcf/VcfFormat.cpp new file mode 100644 index 0000000..005e5a7 --- /dev/null +++ b/src/vcf/VcfFormat.cpp @@ -0,0 +1,551 @@ +// Author: Derek Barnett + +#include "../PbbamInternalConfig.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace PacBio { +namespace VCF { + +namespace { // anonymous + +// using htslib's current version for better compatibility +static constexpr const char current_version[] = "VCFv4.2"; + +namespace Tokens { + +static constexpr const char file_format[] = "fileformat"; + +static constexpr const char double_hash[] = "##"; +static constexpr const char contig_lead[] = "##contig=<"; +static constexpr const char filter_lead[] = "##FILTER=<"; +static constexpr const char format_lead[] = "##FORMAT=<"; +static constexpr const char info_lead[] = "##INFO=<"; +static constexpr const char chrom_lead[] = "#CHROM"; + +static constexpr const char id[] = "ID"; +static constexpr const char number[] = "Number"; +static constexpr const char type[] = "Type"; +static constexpr const char description[] = "Description"; +static constexpr const char source[] = "Source"; +static constexpr const char version[] = "Version"; + +} // namespace Tokens + +std::string QuotedText(const std::string& d) { return "\"" + d + "\""; } + +std::string UnquotedText(const std::string& d) +{ + if (d.size() < 2 || d.front() != '"' || d.back() != '"') + throw std::runtime_error{"VcfFormat: description text is not quoted: " + d}; + return d.substr(1, d.size() - 2); +} + +} // namespace anonymous + +const char* VcfFormat::CurrentVersion() { return current_version; } + +std::string VcfFormat::FormattedContigDefinition(const ContigDefinition& def) +{ + std::ostringstream text; + + // ID + text << Tokens::contig_lead << Tokens::id << '=' << def.Id(); + + // attributes + if (!def.Attributes().empty()) { + text << ','; + bool first = true; + for (const auto& attr : def.Attributes()) { + if (!first) text << ','; + text << attr.first << '=' << attr.second; + first = false; + } + } + text << '>'; + return text.str(); +} + +std::string VcfFormat::FormattedFilterDefinition(const FilterDefinition& def) +{ + std::ostringstream text; + text << Tokens::filter_lead << Tokens::id << '=' << def.Id() << ',' << Tokens::description + << '=' << QuotedText(def.Description()) << '>'; + return text.str(); +} + +std::string VcfFormat::FormattedFormatDefinition(const FormatDefinition& def) +{ + std::ostringstream text; + text << Tokens::format_lead << Tokens::id << '=' << def.Id() << ',' << Tokens::number << '=' + << def.Number() << ',' << Tokens::type << '=' << def.Type() << ',' << Tokens::description + << '=' << QuotedText(def.Description()) << '>'; + return text.str(); +} + +std::string VcfFormat::FormattedGeneralDefinition(const GeneralDefinition& def) +{ + std::ostringstream text; + text << Tokens::double_hash << def.Id() << '=' << def.Text(); + return text.str(); +} + +std::string VcfFormat::FormattedInfoDefinition(const InfoDefinition& def) +{ + std::ostringstream text; + text << Tokens::info_lead << Tokens::id << '=' << def.Id() << ',' << Tokens::number << '=' + << def.Number() << ',' << Tokens::type << '=' << def.Type() << ',' << Tokens::description + << '=' << QuotedText(def.Description()); + + if (def.Source().is_initialized() && !def.Source().get().empty()) + text << ',' << Tokens::source << '=' << QuotedText(def.Source().get()); + + if (def.Version().is_initialized() && !def.Version().get().empty()) + text << ',' << Tokens::version << '=' << QuotedText(def.Version().get()); + + text << '>'; + return text.str(); +} + +std::string VcfFormat::FormattedHeader(const VcfHeader& header) +{ + std::ostringstream out; + + const auto& fileformat = header.GeneralDefinition(Tokens::file_format); + out << FormattedGeneralDefinition(fileformat) << '\n'; + + // remaining general definiitions + for (const auto& def : header.GeneralDefinitions()) { + if (def.Id() != Tokens::file_format) out << FormattedGeneralDefinition(def) << '\n'; + } + + // ##contig + for (const auto& contig : header.ContigDefinitions()) + out << FormattedContigDefinition(contig) << '\n'; + + // ##FILTER + for (const auto& filter : header.FilterDefinitions()) + out << FormattedFilterDefinition(filter) << '\n'; + + // ##INFO + for (const auto& info : header.InfoDefinitions()) + out << FormattedInfoDefinition(info) << '\n'; + + // ##FORMAT + for (const auto& format : header.FormatDefinitions()) + out << FormattedFormatDefinition(format) << '\n'; + + // fixed headers + out << "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO"; + + // samples + const auto& samples = header.Samples(); + if (!samples.empty()) { + out << "\tFORMAT"; + for (const auto& sample : samples) + out << '\t' << sample; + } + + return out.str(); +} + +ContigDefinition VcfFormat::ParsedContigDefinition(std::string line) +{ + // should already be checked by "normal" code path + assert(line.find(Tokens::contig_lead) == 0); + + // substring between brackets + const auto lastBracketPos = line.find_last_of('>'); + if (lastBracketPos == std::string::npos) + throw std::runtime_error{"VcfFormat: malformed ##contig line: " + line}; + line = std::string(line.cbegin() + 10, line.cbegin() + lastBracketPos); + + std::string id; + std::vector> attributes; + + const auto fields = PacBio::BAM::Split(line, ','); + for (const auto& field : fields) { + const auto tokens = PacBio::BAM::Split(field, '='); + if (tokens.size() != 2) { + throw std::runtime_error{"VcfFormat: malformed ##contig line: " + line}; + } + if (tokens[0] == Tokens::id) + id = tokens[1]; + else + attributes.push_back(std::make_pair(tokens[0], tokens[1])); + } + + return ContigDefinition{std::move(id), std::move(attributes)}; +} + +FilterDefinition VcfFormat::ParsedFilterDefinition(std::string line) +{ + // should already be checked by "normal" code path + assert(line.find(Tokens::filter_lead) == 0); + + // substring between brackets + const auto lastBracketPos = line.find_last_of('>'); + if (lastBracketPos == std::string::npos) + throw std::runtime_error{"VcfFormat: malformed FILTER line: " + line}; + line = std::string(line.cbegin() + 10, line.cbegin() + lastBracketPos); + + std::string id; + std::string description; + + const auto fields = PacBio::BAM::Split(line, ','); + for (const auto& field : fields) { + const auto tokens = PacBio::BAM::Split(field, '='); + if (tokens.size() != 2) { + throw std::runtime_error{"VcfFormat: malformed FILTER line: " + line}; + } + if (tokens[0] == Tokens::id) + id = tokens[1]; + else if (tokens[0] == Tokens::description) { + description = UnquotedText(tokens[1]); + } else + throw std::runtime_error{"VcfFormat: unrecognized FILTER field: " + tokens[0]}; + } + + return FilterDefinition{std::move(id), std::move(description)}; +} + +FormatDefinition VcfFormat::ParsedFormatDefinition(std::string line) +{ + // should already be checked by "normal" code path + assert(line.find(Tokens::format_lead) == 0); + + // substring between brackets + const auto lastBracketPos = line.find_last_of('>'); + if (lastBracketPos == std::string::npos) + throw std::runtime_error{"VcfFormat: malformed FORMAT line: " + line}; + line = std::string(line.cbegin() + 10, line.cbegin() + lastBracketPos); + + std::string id; + std::string number; + std::string type; + std::string description; + + const auto fields = PacBio::BAM::Split(line, ','); + for (const auto& field : fields) { + const auto tokens = PacBio::BAM::Split(field, '='); + if (tokens.size() != 2) { + throw std::runtime_error{"VcfFormat: malformed FORMAT line: " + line}; + } + if (tokens[0] == Tokens::id) + id = tokens[1]; + else if (tokens[0] == Tokens::number) + number = tokens[1]; + else if (tokens[0] == Tokens::type) + type = tokens[1]; + else if (tokens[0] == Tokens::description) { + description = UnquotedText(tokens[1]); + } else + throw std::runtime_error{"VcfFormat: unrecognized FORMAT field: " + tokens[0]}; + } + + return FormatDefinition{std::move(id), std::move(number), std::move(type), + std::move(description)}; +} + +GeneralDefinition VcfFormat::ParsedGeneralDefinition(const std::string& line) +{ + const auto tokens = PacBio::BAM::Split(line, '='); + if (tokens.size() != 2 || tokens[0].find(Tokens::double_hash) != 0) { + throw std::runtime_error{"VcfFormat: malformed header line: " + line}; + } + + return GeneralDefinition{tokens[0].substr(2), tokens[1]}; +} + +InfoDefinition VcfFormat::ParsedInfoDefinition(std::string line) +{ + // should already be checked by "normal" code path + assert(line.find(Tokens::info_lead) == 0); + + // substring between brackets + const auto lastBracketPos = line.find_last_of('>'); + if (lastBracketPos == std::string::npos) + throw std::runtime_error{"VcfFormat: malformed INFO line: " + line}; + line = std::string(line.cbegin() + 8, line.cbegin() + lastBracketPos); + + std::string id; + std::string number; + std::string type; + std::string description; + std::string source; + std::string version; + + const auto fields = PacBio::BAM::Split(line, ','); + for (const auto& field : fields) { + const auto tokens = PacBio::BAM::Split(field, '='); + if (tokens.size() != 2) { + throw std::runtime_error{"VcfFormat: malformed INFO line: " + line}; + } + if (tokens[0] == Tokens::id) + id = tokens[1]; + else if (tokens[0] == Tokens::number) + number = tokens[1]; + else if (tokens[0] == Tokens::type) + type = tokens[1]; + else if (tokens[0] == Tokens::description) { + description = UnquotedText(tokens[1]); + } else if (tokens[0] == Tokens::source) { + source = UnquotedText(tokens[1]); + } else if (tokens[0] == Tokens::version) { + version = UnquotedText(tokens[1]); + } else + throw std::runtime_error{"VcfFormat: unrecognized INFO field: " + tokens[0]}; + } + + return InfoDefinition{std::move(id), std::move(number), std::move(type), + std::move(description), std::move(source), std::move(version)}; +} + +VcfHeader VcfFormat::ParsedHeader(const std::string& hdrText) +{ + VcfHeader hdr; + + std::istringstream text{hdrText}; + std::string line; + + // quick check for fileformat - should be the first line + std::getline(text, line); + { + auto genDef = ParsedGeneralDefinition(line); + if (genDef.Id() != Tokens::file_format) + throw std::runtime_error{"VcfFormat: file must begin with #fileformat line"}; + hdr.AddGeneralDefinition(std::move(genDef)); + } + + // read through rest of header + bool chromLineFound = false; + for (; std::getline(text, line);) { + if (line.empty()) continue; + + // info line + if (line.find(Tokens::info_lead) == 0) hdr.AddInfoDefinition(ParsedInfoDefinition(line)); + + // filter line + else if (line.find(Tokens::filter_lead) == 0) + hdr.AddFilterDefinition(ParsedFilterDefinition(line)); + + // format line + else if (line.find(Tokens::format_lead) == 0) + hdr.AddFormatDefinition(ParsedFormatDefinition(line)); + + // contig line + else if (line.find(Tokens::contig_lead) == 0) + hdr.AddContigDefinition(ParsedContigDefinition(line)); + + // general comment line + // + // NOTE: Check this after all other specific header line types. This + // catches all remaining lines starting with "##" + // + else if (line.find(Tokens::double_hash) == 0) + hdr.AddGeneralDefinition(ParsedGeneralDefinition(line)); + + // CHROM line (maybe w/ samples) + else if (line.find(Tokens::chrom_lead) == 0) { + std::vector samples; + + // If samples are present, skip the fixed colums & FORMAT column (9) + // and read the remaining column labels as sample names. + // + auto columns = PacBio::BAM::Split(line, '\t'); + for (size_t i = 9; i < columns.size(); ++i) + samples.push_back(std::move(columns[i])); + hdr.Samples(std::move(samples)); + + // quit header parsing after CHROM line + chromLineFound = true; + break; + } else + throw std::runtime_error{"VcfFormat: unexpected line found in header:\n" + line}; + } + + if (!chromLineFound) throw std::runtime_error{"VcfFormat: CHROM column line is missing"}; + + return hdr; +} + +VcfHeader VcfFormat::HeaderFromFile(const std::string& fn) +{ + std::ifstream in(fn); + return HeaderFromStream(in); +} + +VcfHeader VcfFormat::HeaderFromStream(std::istream& in) +{ + std::stringstream text; + + std::string line; + while (std::getline(in, line)) { + if (line.empty()) continue; + if (line.front() == '#') + text << line << '\n'; + else + break; + } + + return ParsedHeader(text.str()); +} + +InfoField VcfFormat::ParsedInfoField(const std::string& text) +{ + const auto& tokens = PacBio::BAM::Split(text, '='); + if (tokens.empty()) throw std::runtime_error{"VcfFormat: malformed INFO field: " + text}; + + // required ID + InfoField result; + result.id = tokens.at(0); + if (tokens.size() == 1) return result; + + // optional value or values + const auto& valueStr = tokens.at(1); + const auto commaFound = valueStr.find(','); + if (commaFound != std::string::npos) { + std::vector values; + for (auto&& value : PacBio::BAM::Split(valueStr, ',')) + values.push_back(std::move(value)); + result.values = std::move(values); + } else + result.value = valueStr; + + return result; +} + +std::vector VcfFormat::ParsedInfoFields(const std::string& text) +{ + std::vector result; + const auto& fields = PacBio::BAM::Split(text, ';'); + for (const auto& field : fields) + result.push_back(ParsedInfoField(field)); + return result; +} + +GenotypeField VcfFormat::ParsedGenotypeField(const std::string& field) +{ + GenotypeField result; + const auto fieldValues = PacBio::BAM::Split(field, ':'); + for (const auto& fieldValue : fieldValues) { + GenotypeData data; + const auto genotypeDataValues = PacBio::BAM::Split(fieldValue, ','); + if (genotypeDataValues.size() == 1) + data.value = genotypeDataValues.at(0); + else + data.values = genotypeDataValues; + result.data.push_back(std::move(data)); + } + return result; +} + +VcfVariant VcfFormat::ParsedVariant(const std::string& line) +{ + const auto fields = PacBio::BAM::Split(line, '\t'); + if (fields.size() < 7) + throw std::runtime_error{"VcfFormat: record is missing required fields: " + line}; + + // CHROM POS ID REF ALT REF + auto chrom = fields.at(0); + auto pos = std::stoi(fields.at(1)); + auto id = fields.at(2); + auto ref = fields.at(3); + auto alt = fields.at(4); + + VcfVariant var{std::move(id), std::move(chrom), std::move(pos), std::move(ref), std::move(alt)}; + + // QUAL + const auto& qualStr = fields.at(5); + const float qual = (qualStr == "." ? NAN : stof(qualStr)); + var.Quality(qual); + + // FILTER + auto filter = fields.at(6); + var.Filter(std::move(filter)); + + // INFO (allow empty) + if (fields.size() >= 8) var.InfoFields(ParsedInfoFields(fields.at(7))); + + // GENOTYPE (samples) + if (fields.size() > 9) { + var.GenotypeIds(PacBio::BAM::Split(fields.at(8), ':')); + + std::vector genotypes; + for (size_t i = 9; i < fields.size(); ++i) + genotypes.emplace_back(ParsedGenotypeField(fields.at(i))); + var.Genotypes(std::move(genotypes)); + } + + return var; +} + +std::string VcfFormat::FormattedInfoField(const InfoField& field) +{ + std::ostringstream out; + out << field.id; + if (field.value.is_initialized()) + out << '=' << field.value.get(); + else if (field.values.is_initialized()) + out << '=' << PacBio::BAM::Join(field.values.get(), ','); + return out.str(); +} + +std::string VcfFormat::FormattedInfoFields(const std::vector& fields) +{ + std::vector result; + for (const auto& field : fields) + result.push_back(FormattedInfoField(field)); + return PacBio::BAM::Join(result, ';'); +} + +std::string VcfFormat::FormattedGenotypeField(const GenotypeField& field) +{ + std::string result; + bool firstDataEntry = true; + for (const auto& d : field.data) { + if (!firstDataEntry) result += ':'; + if (d.value.is_initialized()) + result += d.value.get(); + else { + assert(d.values.is_initialized()); + result += PacBio::BAM::Join(d.values.get(), ','); + } + firstDataEntry = false; + } + return result; +} + +std::string VcfFormat::FormattedVariant(const VcfVariant& var) +{ + std::ostringstream out; + out << var.Chrom() << '\t' << var.Position() << '\t' << var.Id() << '\t' << var.RefAllele() + << '\t' << var.AltAllele() << '\t' + << (var.IsQualityMissing() ? "." : std::to_string(var.Quality())) << '\t' << var.Filter() + << '\t' << FormattedInfoFields(var.InfoFields()); + + const auto& genotypeIds = var.GenotypeIds(); + if (!genotypeIds.empty()) { + out << '\t' << PacBio::BAM::Join(genotypeIds, ':'); + const auto& genotypes = var.Genotypes(); + for (const auto& genotype : genotypes) + out << '\t' << FormattedGenotypeField(genotype); + } + return out.str(); +} + +} // namespace VCF +} // namespace PacBio diff --git a/src/vcf/VcfHeader.cpp b/src/vcf/VcfHeader.cpp new file mode 100644 index 0000000..ff2f07d --- /dev/null +++ b/src/vcf/VcfHeader.cpp @@ -0,0 +1,234 @@ +// Author: Derek Barnett + +#include "../PbbamInternalConfig.h" + +#include + +#include +#include + +#include + +namespace PacBio { +namespace VCF { + +static_assert(std::is_copy_constructible::value, + "VcfHeader(const VcfHeader&) is not = default"); +static_assert(std::is_copy_assignable::value, + "VcfHeader& operator=(const VcfHeader&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "VcfHeader(VcfHeader&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value, + "VcfHeader& operator=(VcfHeader&&) is not = noexcept"); + +VcfHeader::VcfHeader() { Version(VcfFormat::CurrentVersion()); } + +VcfHeader::VcfHeader(const std::string& hdrText) { *this = VcfFormat::ParsedHeader(hdrText); } + +VcfHeader& VcfHeader::AddContigDefinition(PacBio::VCF::ContigDefinition contig) +{ + const auto found = contigLookup_.find(contig.Id()); + if (found == contigLookup_.cend()) { + contigLookup_.insert({contig.Id(), contigDefinitions_.size()}); + contigDefinitions_.push_back(std::move(contig)); + } else + contigDefinitions_.at(found->second) = std::move(contig); + return *this; +} + +VcfHeader& VcfHeader::AddFilterDefinition(PacBio::VCF::FilterDefinition filter) +{ + const auto found = filterLookup_.find(filter.Id()); + if (found == filterLookup_.cend()) { + filterLookup_.insert({filter.Id(), filterDefinitions_.size()}); + filterDefinitions_.push_back(std::move(filter)); + } else + filterDefinitions_.at(found->second) = std::move(filter); + return *this; +} + +VcfHeader& VcfHeader::AddFormatDefinition(PacBio::VCF::FormatDefinition format) +{ + const auto found = formatLookup_.find(format.Id()); + if (found == formatLookup_.cend()) { + formatLookup_.insert({format.Id(), formatDefinitions_.size()}); + formatDefinitions_.push_back(std::move(format)); + } else + formatDefinitions_.at(found->second) = std::move(format); + return *this; +} + +VcfHeader& VcfHeader::AddGeneralDefinition(PacBio::VCF::GeneralDefinition def) +{ + const auto found = generalLookup_.find(def.Id()); + if (found == generalLookup_.cend()) { + generalLookup_.insert({def.Id(), generalDefinitions_.size()}); + generalDefinitions_.push_back(std::move(def)); + } else + generalDefinitions_.at(found->second) = std::move(def); + return *this; +} + +VcfHeader& VcfHeader::AddInfoDefinition(PacBio::VCF::InfoDefinition info) +{ + const auto found = infoLookup_.find(info.Id()); + if (found == infoLookup_.cend()) { + infoLookup_.insert({info.Id(), infoDefinitions_.size()}); + infoDefinitions_.push_back(std::move(info)); + } else + infoDefinitions_.at(found->second) = std::move(info); + return *this; +} + +VcfHeader& VcfHeader::AddSample(std::string sample) +{ + const auto found = sampleLookup_.find(sample); + if (found == sampleLookup_.cend()) { + sampleLookup_.insert({sample, samples_.size()}); + samples_.push_back(std::move(sample)); + } else + samples_.at(found->second) = std::move(sample); + return *this; +} + +const std::vector& VcfHeader::ContigDefinitions() const +{ + return contigDefinitions_; +} + +const PacBio::VCF::ContigDefinition& VcfHeader::ContigDefinition(const std::string& id) const +{ + return contigDefinitions_.at(contigLookup_.at(id)); +} + +VcfHeader& VcfHeader::ContigDefinitions(std::vector defs) +{ + contigDefinitions_.clear(); + contigLookup_.clear(); + for (auto&& def : defs) + AddContigDefinition(std::move(def)); + return *this; +} + +const std::string& VcfHeader::FileDate() const +{ + return generalDefinitions_.at(generalLookup_.at("fileDate")).Text(); +} + +VcfHeader& VcfHeader::FileDate(std::string fileDate) +{ + AddGeneralDefinition({"fileDate", std::move(fileDate)}); + return *this; +} + +const std::vector& VcfHeader::FilterDefinitions() const +{ + return filterDefinitions_; +} + +const PacBio::VCF::FilterDefinition& VcfHeader::FilterDefinition(const std::string& id) const +{ + return filterDefinitions_.at(filterLookup_.at(id)); +} + +VcfHeader& VcfHeader::FilterDefinitions(std::vector defs) +{ + filterDefinitions_.clear(); + filterLookup_.clear(); + for (auto&& def : defs) + AddFilterDefinition(std::move(def)); + return *this; +} + +const std::vector& VcfHeader::FormatDefinitions() const +{ + return formatDefinitions_; +} + +const PacBio::VCF::FormatDefinition& VcfHeader::FormatDefinition(const std::string& id) const +{ + return formatDefinitions_.at(formatLookup_.at(id)); +} + +VcfHeader& VcfHeader::FormatDefinitions(std::vector defs) +{ + formatDefinitions_.clear(); + formatLookup_.clear(); + for (auto&& def : defs) + AddFormatDefinition(std::move(def)); + return *this; +} + +const std::vector& VcfHeader::GeneralDefinitions() const +{ + return generalDefinitions_; +} + +const PacBio::VCF::GeneralDefinition& VcfHeader::GeneralDefinition(const std::string& id) const +{ + return generalDefinitions_.at(generalLookup_.at(id)); +} + +VcfHeader& VcfHeader::GeneralDefinitions(std::vector defs) +{ + generalDefinitions_.clear(); + generalLookup_.clear(); + for (auto&& def : defs) + AddGeneralDefinition(std::move(def)); + return *this; +} + +const std::vector& VcfHeader::InfoDefinitions() const +{ + return infoDefinitions_; +} +const PacBio::VCF::InfoDefinition& VcfHeader::InfoDefinition(const std::string& id) const +{ + return infoDefinitions_.at(infoLookup_.at(id)); +} + +VcfHeader& VcfHeader::InfoDefinitions(std::vector defs) +{ + infoDefinitions_.clear(); + infoLookup_.clear(); + for (auto&& def : defs) + AddInfoDefinition(std::move(def)); + return *this; +} + +size_t VcfHeader::NumLines() const +{ + // +1 for #CHROM line + return generalDefinitions_.size() + contigDefinitions_.size() + infoDefinitions_.size() + + filterDefinitions_.size() + formatDefinitions_.size() + 1; +} + +const Sample& VcfHeader::SampleAt(size_t index) const { return samples_.at(index); } + +size_t VcfHeader::IndexOfSample(const Sample& sample) const { return sampleLookup_.at(sample); } + +const std::vector& VcfHeader::Samples() const { return samples_; } + +VcfHeader& VcfHeader::Samples(std::vector names) +{ + samples_.clear(); + sampleLookup_.clear(); + for (auto&& name : names) + AddSample(std::move(name)); + return *this; +} + +const std::string& VcfHeader::Version() const +{ + return generalDefinitions_.at(generalLookup_.at("fileformat")).Text(); +} + +VcfHeader& VcfHeader::Version(std::string version) +{ + AddGeneralDefinition({"fileformat", std::move(version)}); + return *this; +} + +} // namespace VCF +} // namespace PacBio diff --git a/src/vcf/VcfHeaderTypes.cpp b/src/vcf/VcfHeaderTypes.cpp new file mode 100644 index 0000000..73ab8c2 --- /dev/null +++ b/src/vcf/VcfHeaderTypes.cpp @@ -0,0 +1,233 @@ +#include "../PbbamInternalConfig.h" + +#include "pbbam/vcf/VcfHeaderTypes.h" + +#include +#include + +#include + +namespace PacBio { +namespace VCF { + +// ------------------- +// ContigDefinition +// ------------------- + +static_assert(std::is_copy_constructible::value, + "ContigDefinition(const ContigDefinition&) is not = default"); +static_assert(std::is_copy_assignable::value, + "ContigDefinition& operator=(const ContigDefinition&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "ContigDefinition(ContigDefinition&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +ContigDefinition::ContigDefinition(std::string id) : ContigDefinition{std::move(id), {}} {} + +ContigDefinition::ContigDefinition(std::string id, + std::vector> attributes) + : id_{std::move(id)}, attributes_{std::move(attributes)} +{ + if (id_.empty()) + throw std::runtime_error{"VcfFormat: ##contig definition in header has empty ID field"}; +} + +ContigDefinition& ContigDefinition::AddAttribute(std::string id, std::string value) +{ + return AddAttribute(std::make_pair(std::move(id), std::move(value))); +} + +ContigDefinition& ContigDefinition::AddAttribute(std::pair attribute) +{ + attributes_.push_back(std::move(attribute)); + return *this; +} + +const std::vector>& ContigDefinition::Attributes() const +{ + return attributes_; +} + +ContigDefinition& ContigDefinition::Attributes( + std::vector> attributes) +{ + attributes_ = std::move(attributes); + return *this; +} + +const std::string& ContigDefinition::Id() const { return id_; } + +// ------------------- +// FilterDefinition +// ------------------- + +static_assert(std::is_copy_constructible::value, + "FilterDefinition(const FilterDefinition&) is not = default"); +static_assert(std::is_copy_assignable::value, + "FilterDefinition& operator=(const FilterDefinition&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "FilterDefinition(FilterDefinition&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +FilterDefinition::FilterDefinition(std::string id, std::string description) + : id_{std::move(id)}, description_{std::move(description)} +{ + if (id_.empty()) + throw std::runtime_error{"VcfFormat: FILTER definition in header has empty ID field"}; + + if (description_.empty()) + throw std::runtime_error{ + "VcfFormat: FILTER definition in header has empty Description field"}; +} + +const std::string& FilterDefinition::Description() const { return description_; } + +const std::string& FilterDefinition::Id() const { return id_; } + +// ------------------- +// FormatDefinition +// ------------------- + +static_assert(std::is_copy_constructible::value, + "FormatDefinition(const FormatDefinition&) is not = default"); +static_assert(std::is_copy_assignable::value, + "FormatDefinition& operator=(const FormatDefinition&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "FormatDefinition(FormatDefinition&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +FormatDefinition::FormatDefinition(std::string id, std::string number, std::string type, + std::string description) + : id_{std::move(id)} + , number_{std::move(number)} + , type_{std::move(type)} + , description_{std::move(description)} +{ + if (id_.empty()) + throw std::runtime_error{"VcfFormat: FORMAT definition in header has empty ID field"}; + + if (number_.empty()) + throw std::runtime_error{"VcfFormat: FORMAT definition in header has empty Number field"}; + + if (type_.empty()) + throw std::runtime_error{"VcfFormat: FORMAT definition in header has empty Type field"}; + + if (description_.empty()) + throw std::runtime_error{ + "VcfFormat: FORMAT definition in header has empty Description field"}; +} + +const std::string& FormatDefinition::Description() const { return description_; } + +const std::string& FormatDefinition::Id() const { return id_; } + +const std::string& FormatDefinition::Number() const { return number_; } + +const std::string& FormatDefinition::Type() const { return type_; } + +// ------------------- +// GeneralDefinition +// ------------------- + +static_assert(std::is_copy_constructible::value, + "GeneralDefinition(const GeneralDefinition&) is not = default"); +static_assert(std::is_copy_assignable::value, + "GeneralDefinition& operator=(const GeneralDefinition&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "GeneralDefinition(GeneralDefinition&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +GeneralDefinition::GeneralDefinition(std::string id, std::string text) + : id_{std::move(id)}, text_{std::move(text)} +{ + if (id_.empty()) + throw std::runtime_error{ + "VcfFormat: general metadata definition in header has empty label"}; + + if (text_.empty()) + throw std::runtime_error{ + "VcfFormat: general metadata definition in header has empty value"}; +} + +const std::string& GeneralDefinition::Id() const { return id_; } + +const std::string& GeneralDefinition::Text() const { return text_; } + +// ------------------- +// InfoDefinition +// ------------------- + +static_assert(std::is_copy_constructible::value, + "InfoDefinition(const InfoDefinition&) is not = default"); +static_assert(std::is_copy_assignable::value, + "InfoDefinition& operator=(const InfoDefinition&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "InfoDefinition(InfoDefinition&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +InfoDefinition::InfoDefinition(std::string id, std::string number, std::string type, + std::string description, std::string source, std::string version) + : id_{std::move(id)} + , number_{std::move(number)} + , type_{std::move(type)} + , description_{std::move(description)} +{ + // verify required fields + if (id_.empty()) + throw std::runtime_error{"VcfFormat: INFO definition in header has empty ID field"}; + + if (number_.empty()) + throw std::runtime_error{"VcfFormat: INFO definition in header has empty Number field"}; + + if (type_.empty()) + throw std::runtime_error{"VcfFormat: INFO definition in header has empty Type field"}; + + if (description_.empty()) + throw std::runtime_error{ + "VcfFormat: INFO definition in header has empty Description field"}; + + if (!source.empty()) source_ = std::move(source); + if (!version.empty()) version_ = std::move(version); +} + +const std::string& InfoDefinition::Description() const { return description_; } + +const std::string& InfoDefinition::Id() const { return id_; } + +const std::string& InfoDefinition::Number() const { return number_; } + +const boost::optional& InfoDefinition::Source() const { return source_; } + +InfoDefinition& InfoDefinition::Source(std::string s) +{ + source_ = std::move(s); + return *this; +} + +const std::string& InfoDefinition::Type() const { return type_; } + +const boost::optional& InfoDefinition::Version() const { return version_; } + +InfoDefinition& InfoDefinition::Version(std::string v) +{ + version_ = std::move(v); + return *this; +} + +} // namespace VCF +} // namespace PacBio diff --git a/src/vcf/VcfQuery.cpp b/src/vcf/VcfQuery.cpp new file mode 100644 index 0000000..11b7dd5 --- /dev/null +++ b/src/vcf/VcfQuery.cpp @@ -0,0 +1,33 @@ +#include "../PbbamInternalConfig.h" + +#include + +#include +#include + +namespace PacBio { +namespace VCF { + +static_assert(!std::is_copy_constructible::value, + "VcfQuery(const VcfQuery&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "VcfQuery& operator=(const VcfQuery&) is not = delete"); + +static_assert(std::is_nothrow_move_constructible::value == + std::is_nothrow_move_constructible::value, + ""); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +VcfQuery::VcfQuery(std::string fn) : VcfQuery{VcfFile{std::move(fn)}} {} + +VcfQuery::VcfQuery(const VcfFile& file) + : PacBio::BAM::internal::QueryBase(), reader_{file} +{ +} + +bool VcfQuery::GetNext(VcfVariant& var) { return reader_.GetNext(var); } + +} // namespace VCF +} // namespace PacBio diff --git a/src/vcf/VcfReader.cpp b/src/vcf/VcfReader.cpp new file mode 100644 index 0000000..e53edbc --- /dev/null +++ b/src/vcf/VcfReader.cpp @@ -0,0 +1,55 @@ +// Author: Derek Barnett + +#include "../PbbamInternalConfig.h" + +#include + +#include +#include + +namespace PacBio { +namespace VCF { + +static_assert(!std::is_copy_constructible::value, + "VcfReader(const VcfReader&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "VcfReader& operator=(const VcfReader&) is not = delete"); + +static_assert(std::is_nothrow_move_constructible::value == + std::is_nothrow_move_constructible::value, + ""); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +VcfReader::VcfReader(std::string fn) : VcfReader{VcfFile{std::move(fn)}} {} + +VcfReader::VcfReader(const VcfFile& file) : in_{file.Filename()}, header_{file.Header()} +{ + // skip header lines + const auto& header = file.Header(); + std::string line; + for (size_t i = header.NumLines(); i > 0; --i) + std::getline(in_, line); + + FetchNext(); +} + +void VcfReader::FetchNext() +{ + line_.clear(); + std::getline(in_, line_); +} + +bool VcfReader::GetNext(VcfVariant& var) +{ + if (line_.empty()) return false; + var = VcfVariant{line_}; + FetchNext(); + return true; +} + +const VcfHeader& VcfReader::Header() const { return header_; } + +} // namespace VCF +} // namespace PacBio diff --git a/src/vcf/VcfSort.cpp b/src/vcf/VcfSort.cpp new file mode 100644 index 0000000..19fa323 --- /dev/null +++ b/src/vcf/VcfSort.cpp @@ -0,0 +1,58 @@ +// Author: Derek Barnett + +#include "../PbbamInternalConfig.h" + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace PacBio { +namespace VCF { + +void SortFile(const VcfFile& file, const std::string& outputFilename) +{ + const auto& header = file.Header(); + + // configure contig sort order + std::unordered_map contigLookup; + const auto& contigDefs = header.ContigDefinitions(); + for (size_t i = 0; i < contigDefs.size(); ++i) { + const auto& contigId = contigDefs.at(i).Id(); + contigLookup.insert(std::make_pair(contigId, i)); + } + + // read & sort variants + std::vector variants; + VcfQuery query{file}; + for (const auto& v : query) + variants.push_back(v); + + std::sort(variants.begin(), variants.end(), + [&contigLookup](const VcfVariant& lhs, const VcfVariant& rhs) { + const auto lhsIdx = contigLookup.at(lhs.Chrom()); + const auto rhsIdx = contigLookup.at(rhs.Chrom()); + const auto lhsPos = lhs.Position(); + const auto rhsPos = rhs.Position(); + return std::tie(lhsIdx, lhsPos) < std::tie(rhsIdx, rhsPos); + }); + + // write results to file + VcfWriter writer{outputFilename, header}; + for (const auto& var : variants) + writer.Write(var); +} + +void SortFile(const std::string& inputFilename, const std::string& outputFilename) +{ + SortFile(VcfFile{inputFilename}, outputFilename); +} + +} // namespace VCF +} // namespace PacBio diff --git a/src/vcf/VcfVariant.cpp b/src/vcf/VcfVariant.cpp new file mode 100644 index 0000000..a0a8aa6 --- /dev/null +++ b/src/vcf/VcfVariant.cpp @@ -0,0 +1,258 @@ +// Author: Derek Barnett + +#include "../PbbamInternalConfig.h" + +#include + +#include +#include +#include + +#include +#include + +namespace PacBio { +namespace VCF { + +static_assert(std::is_copy_constructible::value, + "VcfVariant(const VcfVariant&) is not = default"); +static_assert(std::is_copy_assignable::value, + "VcfVariant& operator=(const VcfVariant&) is not = default"); + +static_assert(std::is_nothrow_move_constructible::value, + "VcfVariant(VcfVariant&&) is not = noexcept"); +static_assert(std::is_nothrow_move_assignable::value == + std::is_nothrow_move_assignable::value, + ""); + +VcfVariant::VcfVariant(const std::string& text) { *this = VcfFormat::ParsedVariant(text); } + +VcfVariant::VcfVariant() : pos_{PacBio::BAM::UnmappedPosition}, qual_{NAN}, filter_{"PASS"} {} + +VcfVariant::VcfVariant(std::string id, std::string chrom, PacBio::BAM::Position pos, + std::string refAllele, std::string altAllele) + : chrom_{std::move(chrom)} + , pos_{pos} + , id_{std::move(id)} + , refAllele_{std::move(refAllele)} + , altAllele_{std::move(altAllele)} + , qual_{NAN} + , filter_{"PASS"} +{ +} + +VcfVariant& VcfVariant::AddInfoField(InfoField field) +{ + const auto found = infoLookup_.find(field.id); + if (found == infoLookup_.cend()) { + infoLookup_.insert({field.id, infoFields_.size()}); + infoFields_.push_back(std::move(field)); + } else + infoFields_.at(found->second) = std::move(field); + return *this; +} + +const std::string& VcfVariant::AltAllele() const { return altAllele_; } + +VcfVariant& VcfVariant::AltAllele(std::string altAllele) +{ + altAllele_ = std::move(altAllele); + return *this; +} + +const std::string& VcfVariant::Chrom() const { return chrom_; } + +VcfVariant& VcfVariant::Chrom(std::string chrom) +{ + chrom_ = std::move(chrom); + return *this; +} + +const std::string& VcfVariant::Filter() const { return filter_; } + +VcfVariant& VcfVariant::Filter(std::string filter) +{ + filter_ = std::move(filter); + return *this; +} + +std::vector VcfVariant::GenotypeIds() const { return format_; } + +VcfVariant& VcfVariant::GenotypeIds(std::vector ids) +{ + genotypeDataLookup_.clear(); + + format_ = std::move(ids); + for (size_t i = 0; i < format_.size(); ++i) + genotypeDataLookup_.insert({format_.at(i), i}); + return *this; +} + +std::vector VcfVariant::Genotypes() const { return sampleGenotypes_; } + +VcfVariant& VcfVariant::Genotypes(std::vector genotypes) +{ + sampleGenotypes_ = std::move(genotypes); + return *this; +} + +const boost::optional& VcfVariant::GenotypeValue(const size_t sampleIndex, + const std::string& id) const +{ + const auto& genotypeField = sampleGenotypes_.at(sampleIndex); + const auto genotypeDataIndex = genotypeDataLookup_.at(id); + const auto& genotypeData = genotypeField.data.at(genotypeDataIndex); + return genotypeData.value; +} + +VcfVariant& VcfVariant::GenotypeValue(const size_t sampleIndex, const std::string& id, + boost::optional value) +{ + auto& genotypeField = sampleGenotypes_.at(sampleIndex); + const auto genotypeDataIndex = genotypeDataLookup_.at(id); + auto& genotypeData = genotypeField.data.at(genotypeDataIndex); + genotypeData.value = std::move(value); + return *this; +} + +const boost::optional>& VcfVariant::GenotypeValues( + const size_t sampleIndex, const std::string& id) const +{ + const auto& genotypeField = sampleGenotypes_.at(sampleIndex); + const auto genotypeDataIndex = genotypeDataLookup_.at(id); + const auto& genotypeData = genotypeField.data.at(genotypeDataIndex); + return genotypeData.values; +} + +VcfVariant& VcfVariant::GenotypeValues(const size_t sampleIndex, const std::string& id, + boost::optional> values) +{ + auto& genotypeField = sampleGenotypes_.at(sampleIndex); + const auto genotypeDataIndex = genotypeDataLookup_.at(id); + auto& genotypeData = genotypeField.data.at(genotypeDataIndex); + genotypeData.values = std::move(values); + return *this; +} + +bool VcfVariant::HasInfoField(const std::string& id) const +{ + const auto found = infoLookup_.find(id); + return found != infoLookup_.cend(); +} + +const std::string& VcfVariant::Id() const { return id_; } + +VcfVariant& VcfVariant::Id(std::string id) +{ + id_ = std::move(id); + return *this; +} + +const std::vector& VcfVariant::InfoFields() const { return infoFields_; } + +VcfVariant& VcfVariant::InfoFields(std::vector fields) +{ + infoFields_.clear(); + infoLookup_.clear(); + for (auto&& field : fields) + AddInfoField(std::move(field)); + return *this; +} + +const boost::optional VcfVariant::InfoValue(const std::string& id) const +{ + return infoFields_.at(infoLookup_.at(id)).value; +} + +VcfVariant& VcfVariant::InfoValue(const std::string& id, boost::optional value) +{ + infoFields_.at(infoLookup_.at(id)).value = std::move(value); + return *this; +} + +const boost::optional> VcfVariant::InfoValues(const std::string& id) const +{ + return infoFields_.at(infoLookup_.at(id)).values; +} + +VcfVariant& VcfVariant::InfoValues(const std::string& id, + boost::optional> values) +{ + infoFields_.at(infoLookup_.at(id)).values = std::move(values); + return *this; +} + +bool VcfVariant::IsDeletion() const { return refAllele_.size() > altAllele_.size(); } + +bool VcfVariant::IsInsertion() const { return refAllele_.size() < altAllele_.size(); } + +bool VcfVariant::IsQualityMissing() const { return std::isnan(qual_); } + +bool VcfVariant::IsSampleHeterozygous(const size_t sampleIndex) const +{ + const auto data = GenotypeValue(sampleIndex, "GT"); + auto fields = PacBio::BAM::Split(data.get(), '/'); + if (fields.size() == 1) fields = PacBio::BAM::Split(data.get(), '|'); + + if (fields.size() != 2) + throw std::runtime_error{"VcfFormat: malformatted GT field: " + data.get()}; + + return fields.at(0) != fields.at(1); +} + +bool VcfVariant::IsSamplePhased(const size_t sampleIndex) const +{ + const auto data = GenotypeValue(sampleIndex, "GT"); + const auto phaseFound = data.get().find('|') != std::string::npos; + if (phaseFound) assert(data.get().find('/') == std::string::npos); + return phaseFound; +} + +bool VcfVariant::IsSnp() const +{ + return refAllele_.size() == 1 && altAllele_.size() == 1 && refAllele_[0] != altAllele_[0]; +} + +PacBio::BAM::Position VcfVariant::Position() const { return pos_; } + +VcfVariant& VcfVariant::Position(PacBio::BAM::Position pos) +{ + pos_ = pos; + return *this; +} + +float VcfVariant::Quality() const { return qual_; } + +VcfVariant& VcfVariant::Quality(float qual) +{ + qual_ = qual; + return *this; +} + +const std::string& VcfVariant::RefAllele() const { return refAllele_; } + +VcfVariant& VcfVariant::RefAllele(std::string refAllele) +{ + refAllele_ = std::move(refAllele); + return *this; +} + +VcfVariant& VcfVariant::RemoveInfoField(const std::string& id) +{ + const auto found = infoLookup_.find(id); + if (found == infoLookup_.cend()) return *this; + + const auto currentFields = InfoFields(); + + infoFields_.clear(); + infoLookup_.clear(); + + for (auto&& field : currentFields) { + if (field.id != id) AddInfoField(std::move(field)); + } + + return *this; +} + +} // namespace VCF +} // namespace PacBio diff --git a/src/vcf/VcfWriter.cpp b/src/vcf/VcfWriter.cpp new file mode 100644 index 0000000..f7fbc95 --- /dev/null +++ b/src/vcf/VcfWriter.cpp @@ -0,0 +1,56 @@ +// Author: Derek Barnett + +#include "../PbbamInternalConfig.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include "../FileProducer.h" + +namespace PacBio { +namespace VCF { + +static_assert(!std::is_copy_constructible::value, + "VcfWriter(const VcfWriter&) is not = delete"); +static_assert(!std::is_copy_assignable::value, + "VcfWriter& operator=(const VcfWriter&) is not = delete"); + +struct VcfWriter::VcfWriterPrivate : public PacBio::BAM::FileProducer +{ + VcfWriterPrivate(std::string fn, const VcfHeader& header) + : PacBio::BAM::FileProducer{std::move(fn)}, out_{TempFilename()} + { + out_ << VcfFormat::FormattedHeader(header) << '\n'; + } + + bool Write(const VcfVariant& var) + { + out_ << VcfFormat::FormattedVariant(var) << '\n'; + return true; // TODO: handle errors + } + + std::ofstream out_; +}; + +VcfWriter::VcfWriter(std::string fn, const VcfHeader& header) + : d_{std::make_unique(std::move(fn), header)} +{ +} + +VcfWriter::VcfWriter(VcfWriter&&) noexcept = default; + +VcfWriter& VcfWriter::operator=(VcfWriter&&) noexcept = default; + +VcfWriter::~VcfWriter() = default; + +bool VcfWriter::Write(const VcfVariant& var) { return d_->Write(var); } + +} // namespace VCF +} // namespace PacBio diff --git a/subprojects/gtest.wrap b/subprojects/gtest.wrap new file mode 100644 index 0000000..773a713 --- /dev/null +++ b/subprojects/gtest.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = googletest-release-1.8.0 + +source_url = https://github.com/google/googletest/archive/release-1.8.0.zip +source_filename = gtest-1.8.0.zip +source_hash = f3ed3b58511efd272eb074a3a6d6fb79d7c2e6a0e374323d1e6bcbcc1ef141bf + +patch_url = https://wrapdb.mesonbuild.com/v1/projects/gtest/1.8.0/5/get_zip +patch_filename = gtest-1.8.0-5-wrap.zip +patch_hash = 7eeaede4aa2610a403313b74e04baf91ccfbaef03203d8f56312e22df1834ec5 diff --git a/subprojects/htslib.wrap b/subprojects/htslib.wrap new file mode 100644 index 0000000..2a93dd3 --- /dev/null +++ b/subprojects/htslib.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = htslib-1.9 + +source_url = https://github.com/samtools/htslib/archive/1.9.zip +source_filename = htslib-1.9.zip +source_hash = c4d3ae84014f8a80f5011521f391e917bc3b4f6ebd78e97f238472e95849ec14 + +patch_url = https://wrapdb.mesonbuild.com/v1/projects/htslib/1.9/1/get_zip +patch_filename = htslib-1.9-1-wrap.zip +patch_hash = 02f4a3c64d668d4d09f8bb0f57eb33398e90e6901989f257be6a6716a15bdcdd diff --git a/subprojects/pbcopper.wrap b/subprojects/pbcopper.wrap new file mode 100644 index 0000000..9567a7f --- /dev/null +++ b/subprojects/pbcopper.wrap @@ -0,0 +1,4 @@ +[wrap-git] +directory=pbcopper +url=https://github.com/PacificBiosciences/pbcopper.git +revision=develop diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap new file mode 100644 index 0000000..91c1d4d --- /dev/null +++ b/subprojects/zlib.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = zlib-1.2.11 + +source_url = http://zlib.net/fossils/zlib-1.2.11.tar.gz +source_filename = zlib-1.2.11.tar.gz +source_hash = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 + +patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.11/4/get_zip +patch_filename = zlib-1.2.11-4-wrap.zip +patch_hash = f733976fbfc59e0bcde01aa9469a24eeb16faf0a4280b17e9eaa60a301d75657 diff --git a/tests/data/aligned.bam b/tests/data/aligned.bam new file mode 100644 index 0000000000000000000000000000000000000000..34d81e55ac5340b4db12e5ec01ac7ce662506f26 GIT binary patch literal 786 zcmb2|=3rp}f&Xj_PR>jWj*PJrF6K2Eh_rp&bmxs|4dX1afXrS_R;ye#(Ur4u%$ITK zsC02p(yiXH_x7sYv&7Y(Kl$(f@6S)AX}x^Pr@6v8Z+LetWH$`RuG$mxYt`E?0nPoB zsstR*^Ic`r@bv!`6ZT7?@`+-Pqt;4!p9$QXIIrF~yd;xj73ar(Mm3M$zP59HJX@Kr zUoDH!Y4p%om9|vcMCys=*+`jAQx6ec3-4{~E#p_jmh65$aYE;W)8ZRr6I$kIs`a&B zi1~Q7@AQv@AA5xjk0wuBw&%uYr_QZ0GoF2Z-jup0A$nic?%L)W_w~8o>sGmzul>Dn zZ;8VB7q+Hb5C6Hh;g8YNC$*9~9Oo3={Q3pwS%%)`zpvnz|LjN1{NwcwJp4Cae01J4 zab5E^-o)1@&(xP)d)}Y=mr3fv37#fK1_pVw5Zui8^pd^zVFwY058))r9>`d46?FAGIxBq_0}PwRus*>d8MI z+^y$(SDtUk)~q4a@N?@L8)k#k1^1-g>ettb$X#1~b3?4HrEOLlXWA^z;(AM7&pUe# zO)-?+<8f$T!{5Iu4HqmwrY`!qN+BjxsWp3@Udi`G=6P?P?CG4NvCQjds_>lyi>n*i zcSpN!ek2pIGD?zZdxX9@pVrgAbA9t>_ef^m_LMAC&Sc#-c_WLlvCip;V-beD)uK_M z{abIzwH%Lov*ux_U)0vwuYdNIoyZRU(e!-z+ppVq{$N&moiCs(`M&1D>*7Vn1znyy zFN)?(VC-C0c;`=;sNpe(1+Ixq4Ubk@SD02Ec;jXhbad${*Y+JvUa{tjoQ}D=ehSrc zoj9TPRd!cEtW$_yw>RhcRmI7l|LO_U3w_L8KIOX(FzEZA`A6M2!fWl3IwK+T%k~TQ zwjZ{${X1*u^=0w@I}-oq-~9gniFfKsXN{K`F$WJlwdzgr{hq3mq4n4Kzc?#b+6y;U O%s7)~UA^kigYU|?VZVoxCk1`wNp!3jb!2r+|rUXvj5=;ACONhE-(7a{=w%##BH literal 0 HcmV?d00001 diff --git a/tests/data/aligned.bam.pbi b/tests/data/aligned.bam.pbi new file mode 100644 index 0000000000000000000000000000000000000000..f2cf20768f7ea0ce3884d9a9ffd980fb3b49fbe5 GIT binary patch literal 168 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 literal 0 HcmV?d00001 diff --git a/tests/data/aligned2.bam.pbi b/tests/data/aligned2.bam.pbi new file mode 100644 index 0000000000000000000000000000000000000000..c1e82de96ba933e6ebd44e53673dc034f8e62beb GIT binary patch literal 366 zcmb2|=3rp}f&Xj_PR>jWfsDPA_G`N)N*uR;{_oS`De>QnoUPb+P9zw5JZvlRo_q8W ze}Iujm*dF_W61)aNk{c~l9bjpcD~Elq;X22=;yw@yXK}?oUh*Z{I`v*{k?hl@1I=Q z@mS#M$|v^TJwJ{oUReFi^tj)S-1hH$FR~gBtLT^cKb;2oSK%f{k+ortsD2xmE&oCkhig;vuNGZzjdd3B~Kq+^ECW? zQR3B4MZO|o+x{s@Wbnf)-I?p1q|JULlOS!L}s`n`5y=1sw zx^!OlF7>*Aq`(>d&gD!oA6FDbK0Oq*F(pf9W@Y|;#@~#&LXl2gObiV2Xdx=izzhyx G5CH%q9;8SB literal 0 HcmV?d00001 diff --git a/tests/data/barcoded_read_groups.bam b/tests/data/barcoded_read_groups.bam new file mode 100644 index 0000000000000000000000000000000000000000..4873f7e9df1606ec0550ddc1d037628d8c6931ed GIT binary patch literal 498 zcmb2|=3rp}f&Xj_PR>jWI*d<)PG=o95b#+j{xtrLm#1g6q@zl7r|aLYCoH#SPu5s_ zaAVh7nNNrR_T6H2_Hyn$%QMs78(-g|=Em+#n@8|PnrpMS%2`6k85a&2pcOYP)J zgP-oU+ijKVdT&nWt(ji`JsA@8-qr1MW06u2d?7BF(a_~^U8Iq1MaR46A6IPEf9lRs z@Cg`9@@Rpzg5h*xLc$Mz);m0MPCPt14jlr_Mv`7Z-QHh#zwkctm5`b3z~uNYkWKTM zr<+)2Cr|6jb2_a@&+$~Up6dzSd9KH`HFI;C*DdkqmP;GYSXLi9&L?Ruls#Xu?DrSm zl2TrettOf`HD`1(GEL%|yS1aNMKI4@V$ypKw@WgKJ%6~W^g2f2mmjZ(H{T+ literal 0 HcmV?d00001 diff --git a/tests/data/barcoded_read_groups.bam.pbi b/tests/data/barcoded_read_groups.bam.pbi new file mode 100644 index 0000000000000000000000000000000000000000..368d1d5c3abd1b354f118bd10ca2fca937814435 GIT binary patch literal 126 zcmb2|=3rp}f&Xj_PR>jWi45EYpHfni64DY96H*Vb)n$f!UX+~kDx#t3#SB4>w!ZYU zQ?|Gt5BOZ-m?g<2q3|VKBlalA!~g9U|2wXdX#8M5fz|NeelYT?A&39~D{3gS literal 0 HcmV?d00001 diff --git a/tests/data/bed/test.bed b/tests/data/bed/test.bed new file mode 100644 index 0000000..c5f14de --- /dev/null +++ b/tests/data/bed/test.bed @@ -0,0 +1,9 @@ +chr1 213941196 213942363 +chr1 213942363 213943530 +chr1 213943530 213944697 +chr2 158364697 158365864 +chr2 158365864 158367031 +chr3 127477031 127478198 +chr3 127478198 127479365 +chr3 127479365 127480532 +chr3 127480532 127481699 diff --git a/tests/data/bed/test.bed.gz b/tests/data/bed/test.bed.gz new file mode 100644 index 0000000000000000000000000000000000000000..d0cf3e996d76332c226dbb9e2726afa21b2bf632 GIT binary patch literal 119 zcmV--0Eqt|iwFqUvISiL19W9`bS`3LWB^TzF%H8p48&&VH9nm!OYh0jx&I%Mvw+qc z34-_Mi)LUBAic=wyzXC+7ICs4L0U9Cmx49Spi7Hp_&9>JXmvt?4YtOT76menAT7#w ZKZ0~q^hx`Ntwr$6>j4bz7-r!B008g&G?M@T literal 0 HcmV?d00001 diff --git a/tests/data/chemistry.xml b/tests/data/chemistry.xml new file mode 100644 index 0000000..c6a6521 --- /dev/null +++ b/tests/data/chemistry.xml @@ -0,0 +1,9 @@ + + + + FOUND + 1 + 2 + 3.4 + + diff --git a/tests/data/chimera_minimal.fasta b/tests/data/chimera_minimal.fasta new file mode 100644 index 0000000..f2eb86c --- /dev/null +++ b/tests/data/chimera_minimal.fasta @@ -0,0 +1,220 @@ +>Barcode0--0_Cluster1_Phase1_NumReads297 +GCAGGTGCCTTTGCAGAAACAAAGTCAGGGTTCTTCAAGTCACAAAGGGAAGGGCAGGAA +CAACTCTTGCCTCTCAGTCCCACACAAGGCAGCTGTCTCACACTATAGAAAAAAATATTC +ATGAACAAATTCGTATCTGTCACAGTGAGGGGTCACACTTTAAACAGCCCATCGCATGCT +CAATACATCCAATGGAAAGAAACCCCATAGCACAGCTGTGTCCACTGTTCCGCCCAACAC +CCAACACACATCAGGCCCTCCAGGCTCTCACCTTTACAAGCTGTGAGAGACACATCAGAG +CCCTGGGCACTGTCACTGCCTGGGGTAGAACAAAAACAGAACCTGGTCAGATCCCACAGA +AGATGTGGCTAGAGGAGGAATTGTGGGGTGGGTGAGCTCCCCCATGGGCTCCCAAACACA +ATATCCCAAGGACCTCAGGCATCAGCCTCCTTCATACTTACTTGCAGCCTGAGAGTAGCT +CCCTCCTTTTCTATCTGTGGGAAGAAAATGTCCTGTGAGATACCAGAAAGGAGTCAGGGC +CTTAAGGTCCTAGAGGAACCTCCAAGTCTTGGACCTCAGAGAAGTTTCCAGAAATGTGTG +ACTGCAGACCCAGGGCGGGATCAGGAAACATGAAGAAAGCAGGTGTGGGTCCTGGACCAA +CCGCCCTCCTGAAGGTCCTCAGGGACCTTCCCCTGTGACTTGTGACTGCTGGGATCAGGT +CCCATCACCGCTGTAATCAAGGTGATAAATCTGTCCTTCATTTTAACAGGTGCTTTACAA +AAGAGTAAGTGCTGGCACACAGGGCCCAGGCTGGGTAGGCCCATAATTGTGGGTGGTGCT +TCCCAGTAACGAGGCAGGGCACACTTCTACCTGGGTCTTGGAACCCTCAGTGAGACAAGA +AATCTCAGACCCACCCTTCACCCCTTCCCCACCTGAGCTCTTCCTCCTCCACATCACAGC +AGCGACCACAGCTCCAGTGATCACAGCTCCAAAGAGAACCAGGCCAGCAATGATGCCCAC +GATGGGGATGGTGGGCTGGGAAGACGGCTCTGGGAAAAGAGGGGAAGGTGAGGGGCCCTG +ACCCTGCTAAAGGTCAGAGAGGCTCCTGCTTTCCCTAAAAGACATGACACCCCCGTCTCC +CTCCTTACCCCATCTCAGGGTGAGGGGCTTGGGCAAACCCTCATGCTGCACATGGCAGGT +GTATCTCTGCTCCTGTCCAGAAGGCACCACCACAGCCGCCCACTTCTGGAAGGTTCCATC +CCCTGCAGGCCTGGTCTCCACGAGCTCCGTGTCCTGGGTCTGGTCCTCCCCATCCCGCTG +CCAGGTCAGTGTGATCTCCGCAGGGTAGAAGCTCAGGGCCCAGCACCTCAGGGTGGCTTC +ATGGTCAGAGACAGCGTGGTGAGTCATATGCGTTTTGGGGGCGTCTGTCAGGAAGAGTCA +GATCATTCAGGCATTTTGCATCTGTCATGGGACACTCCTCCAGCACACATGTGGCTATCT +TGAGAATGGACAGGACACCTGGGATGGGGAAGGGAGCACAGAACCCAGACACCAGCCTGG +ACACAGGCACCTGGGATAATCTCCTATTCCGTGGAAAATTCTAGTCCCTGAAGAGGGAAC +AGCGACTTCTGGTCCTGACCTGAGTGGAGGCTGAAGGACTCAGAAGTGCTGGACTCAGAC +CCCCACACACATTGAGTGTGAAGCAGAGAACAAGGCCTGAGAGGAAAAGTCACGGGCCCA +AGGCTGCTGCCTGTGTGTGTCAAAGGGAACCACTCATCAGTATTCGAGGGATCGTCTTCC +CGTCATTCCTTCAGAGATTTTATCCCTTAATTGTGTCAGAGAGCAGGGCGGAACCTCAGA +GTCACTCTCTGGTACAGGATCTGGAAACCCAGGAGGATTCCTCTCCCTCAGGACCAGAGG +GAGGGCGATATTCTAGTGTTGGTCCCAATTGTCTCCCCTCCTTGTGGGAGGCCAGCCCGG +GAGATCTACAGGCGATCAGGGAGGCGCCCCGTGGCCCCTGGTACCCGTGCGCTGCAGCGT +CTCCTTCCCGTTCTCCAGGTATCTGCGGAGCCACTCCACGCACGTGCCCTCCAGGTAGGC +TCTCAACTGCTCCGCCACATGGGCCGCCTCCCACTTGTGCTTGGTGGTCTGAGCTGCCAT +GTCCGCCGCGGTCCAAGAGCGCAGGTCCTCTTTCAGGGCGATGTAATCCTTGCCGTCGTA +GGCGTACTGGTGGTACCCGCGGAGGAAGCGCCAGTCCGACCCCACGTCGCAGCCATACAT +CCTCTGGACGGTGTGAGAACCTGGCCCGGACCCCGCGGTCAGCCCGGTCCCCCGAGCCCC +GCCCCGCCCCGACCAACCTGGGGGGATTTTTGGCCTAAACTGAAAATGAAACCGGGTAAA +GGCGCCTGGGCCTCTCCCGGGGCAAGGGTCTCGGGGTCCCGCGGCTTCGGGGCGGATCTC +GGACCCGGAGACTGTGGGCGACCTGGCCCGTCCGTGGGGGATGAGAGGTCGTGACCTGCG +CCCCGGGCCGGGGTCACTCACCGGCCTCGCTCTGGTTGTAGTAGCCGCGCAGGGTCCCCA +GGTCCACTCGGTGAGTCTGTGAGTGGGCCTTCACTTTCCGTGTCTCCCCGTCCCAATACT +CCGGACCCTCCTGCTCTATCCACGGCGCCCGCGGCTCCATCCTCTGGCTCGCGGCGTCGC +TGTCGAACCGCACGAACTGCGTGTCGTCCACGTAGCCCACTGCGATGAAGCGGGGCTCCC +CGCGGCCGGGCCGGGACACGGATGTGAAGAAATACCTCATGGAGTGAGAGCCTGGGGACG +AGGAGTGGCTGAGACCCGCCCGACCCTCCTCCCGGCGCGGCTTCCCGGGTCCTGCGCCCC +CGCCAGGCGGGCCCGTTGCTTCTCCCCACAGAGGCCGTTTCCCTCCCGACCCCGCACTCA +CCCGCCCAGGTCTGGGTCAGGGCCAGAGCCCCCGAGAGTAGCAGGACGAGGGTTCGGGGC +GCCATGACGGCCATCCTCGGCGTCTGGGGAGAATCTGAGTCCCGGTGGGTGCGTGCGGAC +TTTAGAACCGCGACCGCGACGACACTGATTGGCTTCTCTGGAAACCCGACACCCAATGGG +AGTGAGAACTGGGTCCGCGTCGTGAGTATCCA +>Barcode0--0_Cluster3_Phase1_NumReads294 +GCAGGTGCCTTTGCAGAAACAAAGTCAGGGTTCTTCAAGTCACAAAGGGAAGGGCAGGAA +CAACTCTTGCCTCTCAGTCCCACACAAGGCAGCTGTCTCACACTATAGAAAAAAATATTC +ATGAACAAATTCATATCCATCACAGTGAGGGGTCACACCTTAAACAGCCCATCGCATGCT +CAATACATCCAATGCAAAGAAACCCCATAGCACAGCTGTGTCCACTGTTCCGCCCAACAC +CCAACACACATTAGGTCCTCCAAGCTCTCACCTTTACAAGCTGTGAGGGACACATCAGAG +CCCTGGGCACTGTCACTGCCTGGGGTAGAACAAAAACAGAACCTGGTCAGATCCCACAGA +AGATGTGGCTAGAGGAGGAATTGTGAGGTGGGTGGGCTCCCCCATGGGCTCCCAAACACA +ATATCCCAAGGACCTCAGGCATCAGCCTCCTTCATACTTACTTGCAGCCTGAGTGTAACT +CCCTCCTTTTCTATCTGTGAGAAGAAAATGTCCTGTGAGATACCAGAAAGGAGCCAGGGC +CTTAAGGTCCTAGAGGAACCTCCTAGTCTTGGACCCCAGAGAAGTTTCCAGAAATGTGTG +ACTGCAGACCCAGGGCGGGATCAGGAAACATGAAGAAAGCAGGTGTGGGTCCTGGACCAA +TAGCCCTCCTGAGGTCTGTCCTCAGGGACCTTCCCCTGTGACTTGTGACTGCTGGGATCA +GGTCCCATCACCGCCGTAATCAAGGTGATAAATCTGTCCTTCATTTTAACAGGTGCTTTA +CAAAAGAGTAAGTGCTGGCACACAGGGCCCAGACTGGGTAGGCCCATGATTGTGGACGGT +GCTTCCCAGTAATGAGACAGGGCACATTTCTAGCTGGGGCTTGGAACCCTCAGTGAGACA +AGAAATCTCAGACCCCACCCTTCACCCCTTCTCCACCTGAGCTCTTCCTCCTCCACATCA +CGGCAGCGACCACAGCTCCAGTGATCACAGCTCCAAGGAGAACCAGGCCAGCAATGATGC +CCACGATGGGGATGGTGGGCTGGGAAGACAGCTCTGGGAAAAGAGGGGAAGGTGAGGGGC +CCTGACCCTGCTAAAGGTCTCCAGAGAGGCTCCTGCTTTCCCTAAGAGACATGACACCCC +CATCTCCCTCCTTACCCCATCTCAGGGTGAGGGGCTTGGGCAGACCCTCATGCTGCACAT +GGCAGGTGTATCTCTGCTCCTCTCCAGAAGGCACCACCACAGCCGCCCACTTCTGGAAGG +TTCCATCCCCTGCAGGCCTGGTCTCCACGAGCTCCGTGTCCTGGGTCTGGTCCTCCCCAT +CCCGCTGCCAGGTCAGTGTGATCTCCGCAGGGTAGAAGCCCAGGGCCCAGCACCTCAGGG +TGGCCTCATGGTCAGAGATGGGGTGGTGGGTCATATGTGTCTTGGGGGGGTCTGACGGGA +AGAGTCAGAAAATTCAGGCATTTTGCATCTGTCATGGGACACTCCACCAGCACGCATGTG +GCCATCTTGAGAATGGACAGGACACCCGGGATGGGGAAGAGAGCACAGAACCCAGACACC +AGCCTGGACACAGGCACCTGGGATAATCTTCTATTCCCTGAGAAGGGAACAGCGACTTCT +GGTCCTGACCTGAGTGGAGGCTGAGGGACTCAGAAGTGCTGGACTCAGACCCCCACACAC +ATTGAGTGTGAAGCAGAGAACAAGGCCTGAGAGGAAAAGTCACGGGCCCAAGGCTGCTGC +CGGTGTCAAAGGGAACCACTCATCAGTATTCGAGGGATCGTCTTCCCGTCACTCCTTCAG +AGATTTTATCCCTTAATTGTGTCAGAGAGCAGGGCGGAACCTCAGAGTCACTCTCTGGTA +CAGGATCTGGAACCCAGGAGGATTCCTCTCCCTCAGGACCAGAGGGAGGGTGATATTCTA +GTGTTGGTCCCAATTGTCTCCCCTCCTTGTGGGAGGCCAGCCCGGGAGATCTACAGGCGA +TCAGGGAGGCGCCCCGTGGCCCCTGGTACCCGTGCGCTGCAGCGTCTCCTTCCCGTTCTC +CAGGTATCTGCGGAGCCACTCCACGCACGTGCCATCCAGGTAGGCTCTCAACTGCTCCGC +CTCATGGGCCGCCTCCCACTTGCGCTTGGTGATCTGAGCCGCCATGTCCGCCGCGGTCCA +AGAGCGCAGGTCCTCGTTCAGGGCGATGTAATCCTTGCCGTCGTAGGCGTCCTGCCGGTA +CCCGCGGAGGAAGCGCCCGTCCGACCCCACGTCGCAGCCATACATTATCTGGATGGTGTG +AGAACCTGGCCCCGACCCCGCGGTCAGCCCAGTCCCCCGAGCCCCGCCCAGCCCCGACCA +ACCCGGGGGGATTTTTGGCCTAAACTGAAAATGAAACCGGGTAAAGGCGCCTGGGCCTCT +CCCGGGGCAAGGGTCTCGGGGTCCCGCGGCTTCGGGGTGGATCTCGGACCCGGAGACTGT +GGGCGACCTGGCCCGTCCGTGGGGGATGAGGGGTCCTGACCTGCGCCCCCGGCCGGGGTC +ACTCACCGGCCTCGCTCTGGTTGTAGTAGCCGCGCAGGGTCCCCAGGTCCACTCGGTCAG +TCTGTGACTGGGCCTTCACATTCCGTGTCTCCTGGTCCCAATACTCCGGCCCCTCCTGCT +CTATCCACGGCGCCCGCGGCTCCATCCTCTGGCTCGCGGCGTCGCTGTCGAACCGCACGA +ACTGCGTGTCGTCCACGTAGCCCACGGCGATGAAGCGGGGCTCCCCGCGGCCGGGCCGGG +ACACGGATGTGAAGAAATACCTCATGGAGTGGGAGCCTGGGGGCGAGCAGTGGCTGAGAC +CTGCCCGACCCTCGTCCCGGCGCGGCTCCCCCGGTCCTGCGCCCCCGCCAGGAGGGCCCC +TTGCTTCTCCCCGCAGAGGCGGTTTCCCTCCCGACCCCGCACTCACCCGCCCAGGTCTGG +GTCAGGGCCAGGGCCCCCGAGAGTAGCAGGAGGAGGGTTCGGGGCGCCATGACGGCCATC +CTCGGCGTCTGGGGAGAATCTGAGTCCCGGTGGGTGCGTGCGGGCTTTAGAACAGCGACC +GCGACGACACTGATTGGCTTCTCTGGAAACCCGACACCCAATGGGAGTGAGAACTGGGTC +CGCGTCGTGAGTATCCA +>Barcode0--0_Cluster0_Phase2_NumReads92 +CTGGGGAGGAAACACAGGTCAGCATGGGAACAGGGGTCACAGTGGACACGGGGGTGGGCT +GTCTCTCCACCTCCTCACATTATGCTAACAGGGACGCAGACACATTCAGGTGCCTTTGCA +GAAAGAGATGCCAGAGGCTCTTGAAGTCACAAAGGGGAGGAGTGAAGAAATCCTGCATCT +CAGTCCCTCACAAGACAGCTGTCTCAGGCTACAGAAAACAACAGTCATGAACAAATTCTG +GTTAGTCATGGTAAGTGATGACACTCTAAACAGCCCACCACACACGCGAAACATCCCAAT +CAAAGAATCTCCATTACCCAGGCCTTTCCCCTCTGCCCCCTCCCCACCCCACCCCCCCCG +CCCACTCTAGACCCCAAGAATCTCACCTTTTCAAGCTGTGAGAGACACATCAGAGCCCTG +GGCACTGTCGCTGGCTGGAGTAGAACAAAAACAGGACCTGGTCAGAGCCCGCAGGAGACG +TGGGACAGGAGGAATTATGGGGTGGGTGAGCTCCTCCACACTCCCACCCCCACCACTTAC +ACGCAGCCTGAGAGTAGCTCCCTCCTTTTCCACCTGTGGGAAGAAAATGTCCTGTGAGGG +GACTGGGAGGAAGCAGGGCCATGAGATCTTAGAGGAACCTCCTCGTCTTGGACCCAAAAG +GAATTTCCAGAAGTATGACTACAGACCCAAGGCAGGATCAGGAAACACGAGGAAAGCAAG +TGTGGGTCCTGGACCAACTGCCCTCCTAAGGTCTGTCCTTAGCAGGGACCTTCCCCTGAC +TCATGAATGCTGAAATCAGGACCCCAACACCACAACCATCAAGGTGATACATCCGTCCTT +CATTGTCACATGTGCTGCACAAAAGAGTAAGTGCTGGCACACAGGGTCCCAGGCTGCATT +AGCCCCTGTGTGGATGCTGCTTCCCAGTAATGAGGCAGGGAACACTTCTACCTGGGGCTT +GAAACCCCCAGTGGGACAAGAAAACCCAGACCCCACCCCTCACCCCTTCCCTACCTGAGC +TCTTCCTCCTACACATCACAGTAGCGACCACAGCTCCGATGACCACAACTGCTAGGACAG +CCAGGCCAGCAACAATGCCCACGATGGGGATGGTGGACTGGGAAGATGGCTCTGGGAAAG +GAGGGGAAGACGAGGGGCCCTGACCCTGCTGAAGGGCTCCAGAAGGGCTCCTGCTTTCCC +TGAGAAGAGATATGACCCCTCATCCCCCTCCTTACCCCATCTCAGGGTGAGGGGCTTCGG +CAGCCCCTCATGCTGTACATGGCATGTGTATCTCTGCTCTTCTCCAGAAGGCACCACCAC +AGCTGCCCACTTCTGGAAGGTTCTATCTCCTGCTGGTCTGGTCTCCACAAGCTCAGTGTC +CTGAGTTTGGTCCTCGCCATCCCGCTGCCAGGTCAGTGTGATCTCCGCAGGGTAGAAGCC +CAGGGCCCAGCACCTCAGGGTGGCCTCATGGTCAGAGATGGGGTGGTGGGTCACGTGTGT +CTTTGGGGGGTCTGATGGGAAGAGTCAGAAAATTCAGGCGCTTTGCATCTCTCATAGGAC +ACCCTAGGACCACCCATGTGACCAGCCTGAGAATGGACAGGACACCTGGGGTGGGGAAGG +GGCACAGAACCCAGACACCAGCCTGGACGCAGGCACCTGGGATAATCTCCTATTCATTGG +AAAGTTCGAGTCTCTGAGCGGGGAACAGGGACTTCTGCTCCTGATCTGAGTGGAGGTAAA +GTGACTCAGAAGTGCTGGAATCAGAGCCCCAAACACACTGAGTGTGAGGCAGAGAACAAG +GCCTGAGAGGAAAAGTCACGGTTCCCAAGGCTGCTGCAGGGGTCAAAGAGGACCCCTGAT +CAGTATTCTAGGGACTGTCTTCCCCTCCATTTCCTCAGAGACGTCATCCCTTAATTGTCC +TAGAGAGAAGAGGGGGCCCTCAGAGGAAACTCAGGAAAACTCATGCCATTCTCCATTCAA +GGGAGGGCGACATTCTAGCGCTGATCCCATTTTCCTCCTCTTCTCGTGGGAGGCCATCCC +CGGCGACCTATAGGAGATGGGGAAGGCTCCCCACTGCCCCTGGTACCCGCGCGCTGCAGC +GTCTCCTTCCCGTTCTCCAGGTATCTGCGGAGCCACTCCACGCACAGGCCCTCCAGGTAG +GCTCTCAGCTGCTCCGCCACACGGGCCGCCTCCCACTTGCGCTGGGTGATCTGAGCCGCG +GTGTCCGCCGCGGTCCAGGAGCTCAGGTCCTCGTTCAGGGCGATGTAATCCTTGCCGTCG +TAGGCTAACTGGTTATGCCCGCGGAGGAGGCGCCCGTCCGGCCCCAGGTCGCAGCCATAC +ATCGTCTGCCAAGTGTGAGACCCTGGCCCCGGCCCCGCGGTCAGCCCCGTCCCCCGAGCC +CCGCCCCGCCCCGACCAACCCGCGGGGATTTTGGCCTCAACTGAAAATGAAACCGGGTAA +ACGCGCCTGGGGCTCTCGCCGGTCGAGGGTCTGGGCGGGTCCCGCGGCCTCAGGGAGGCG +GATCTCGGACCCGGAGACTCGGGGCGACCCGGGCCGTACGTGGGGGATGGGGAGTCGTGA +CCTGCGCCCCGGGCCGGGGTCACTCACCGGCCTCGCTCTGGTTGTAGTAGCCGCGCAGGT +TCCGCAGGCTCTCTCGGTCAGTCTGTGCCTGGGCCTTGTAGATCTGTGTGTTCCGGTCCC +AATACTCCGGCCCCTCCTGCTCTATCCACGGCGCCCGCGGCTCCTCTCTCGGACTCGCGG +CGTCGCTGTCGAACCTCACGAACTGCGTGTCGTCCACGTAGCCCACTGCGATGAAGCGGG +GCTCCCCGCGGCCGGGCCGGGACATGGCGGTGTAGAAATACCTCATGGAGTGGGAGCCTG +GGGGCGAGGAGGGGCTGAGACCCGCCAGACCCTCCTCCCGGCGCGGCTCCCCGGGTCCTG +CGCCCCCGCCTGCGGTCCCCTCGCTCCTCCCCACAGAGGCCATTTCCCTCCCGACCCGCA +CTCACCGGCCCAGGTCTCGGTCAGGGCCAGGGCCCCCCAGAGCAGCAGGAGGAGGGTTCG +GGGTGCCGTGACCCGCATCTCGGTGTCTGAGGAGACTCTGAGTCCGGGTGGGTGCGTGGG +GACTTTAGAACTGGGACCCCGGCGACACTGATTGGCTTCTCTAGACACCCGACACCCAAT +GGGAGTGGGAAATGGGGACGCGTCACGAGTATCCTGGAAGAAGGACCCGACATAGGTTGG +GAGAAGAAGTGAAACTCGTGGGAGTGGGGAATCCCCAACGCTGCGCCTCCCCAATGCAGA +CGCGGCCCTCGGAGCCTGAGACCCTGAGAGCCCCGTCCGGGACATGGGACTTCGTCCTGA +TCCCTCTTCTCCTACACCAGCCTCTTTGTCACACTGTCTGCC +>Barcode0--0_Cluster1_Phase3_NumReads56 +GCAGGTGCCTTTGCAGAAACAAAGTCAGGGTTCTTCAAGTCACAAAGGGAAGGGCAGGAA +CAACTCTTGCCTCTCAGTCCCACACAAGGCAGCTGTCTCACACTATAGAAAAAAATATTC +ATGAACAAATTCGTATCTGTCACAGTGAGGGGTCACACTTTAAACAGCCCATCGCATGCT +CAATACATCCAATGGAAAGAAACCCCATAGCACAGCTGTGTCCACTGTTCCGCCCAACAC +CCAACACACATCAGGCCCTCCAGGCTCTCACCTTTACAAGCTGTGAGAGACACATCAGAG +CCCTGGGCACTGTCACTGCCTGGGGTAGAACAAAAACAGAACCTGGTCAGATCCCACAGA +AGATGTGGCTAGAGGAGGAATTGTGGGGTGGGTGAGCTCCCCCATGGGCTCCCAAACACA +ATATCCCAAGGACCTCAGGCATCAGCCTCCTTCATACTTACTTGCAGCCTGAGAGTAGCT +CCCTCCTTTTCTATCTGTGGGAAGAAAATGTCCTGTGAGATACCAGAAAGGAGTCAGGGC +CTTAAGGTCCTAGAGGAACCTCCAAGTCTTGGACCTCAGAGAAGTTTCCAGAAATGTGTG +ACTGCAGACCCAGGGCGGGATCAGGAAACATGAAGAAAGCAGGTGTGGGTCCTGGACCAA +CCGCCCTCCTGAAGGTCCTCAGGGACCTTCCCCTGTGACTTGTGACTGCTGGGATCAGGT +CCCATCACCGCTGTAATCAAGGTGATAAATCTGTCCTTCATTTTAACAGGTGCTTTACAA +AAGAGTAAGTGCTGGCACACAGGGCCCAGGCTGGGTAGGCCCATAATTGTGGGTGGTGCT +TCCCAGTAACGAGGCAGGGCACACTTCTACCTGGGTCTTGGAACCCTCAGTGAGACAAGA +AATCTCAGACCCACCCTTCACCCCTTCCCCACCTGAGCTCTTCCTCCTCCACATCACAGC +AGCGACCACAGCTCCAGTGATCACAGCTCCAAAGAGAACCAGGCCAGCAATGATGCCCAC +GATGGGGATGGTGGGCTGGGAAGACGGCTCTGGGAAAAGAGGGGAAGGTGAGGGGCCCTG +ACCCTGCTAAAGGTCAGAGAGGCTCCTGCTTTCCCTAAAAGACATGACACCCCCGTCTCC +CTCCTTACCCCATCTCAGGGTGAGGGGCTTGGGCAAACCCTCATGCTGCACATGGCAGGT +GTATCTCTGCTCCTGTCCAGAAGGCACCACCACAGCCGCCCACTTCTGGAAGGTTCCATC +CCCTGCAGGCCTGGTCTCCACGAGCTCCGTGTCCTGGGTCTGGTCCTCCCCATCCCGCTG +CCAGGTCAGTGTGATCTCCGCAGGGTAGAAGCTCAGGGCCCAGCACCTCAGGGTGGCTTC +ATGGTCAGAGACAGCGTGGTGAGTCATATGCGTTTTGGGGGCGTCTGTCAGGAAGAGTCA +GATCATTCAGGCATTTTGCATCTGTCATGGGACACTCCTCCAGCACACATGTGGCTATCT +TGAGAATGGACAGGACACCTGGGATGGGGAAGGGAGCACAGAACCCAGACACCAGCCTGG +ACACAGGCACCTGGGATAATCTCCTATTCCGTGGAAAATTCTAGTCCCTGAAGAGGGAAC +AGCGACTTCTGGTCCTGACCTGAGTGGAGGCTGAAGGACTCAGAAGTGCTGGACTCAGAC +CCCCACACACATTGAGTGTGAAGCAGAGAACAAGGCCTGAGAGGAAAAGTCACGGGCCCA +AGGCTGCTGCCTGTGTGTGTCAAAGGGAACCACTCATCAGTATTCGAGGGATCGTCTTCC +CGTCATTCCTTCAGAGATTTTATCCCTTAATTGTGTCAGAGAGCAGGGCGGAACCTCAGA +GTCACTCTCTGGTACAGGATCTGGAACCCAGGAGGATTCCTCTCCCTCAGGACCAGAGGG +AGGGCGATATTCTAGTGTTGGTCCCAATTGTCTCCCCTCCTTGTGGGAGGCCAGCCCGGG +AGATCTACAGGCGATCAGGGAGGCGCCCCGTGGCCCCTGGTACCCGTGCGCTGCAGCGTC +TCCTTCCCGTTCTCCAGGTATCTGCGGAGCCACTCCACGCACGTGCCATCCAGGTAGGCT +CTCAACTGCTCCGCCTCATGGGCCGCCTCCCACTTGCGCTTGGTGATCTGAGCCGCCATG +TCCGCCGCGGTCCAAGAGCGCAGGTCCTCGTTCAGGGCGATGTAATCCTTGCCGTCGTAG +GCGTCCTGCCGGTACCCGCGGAGGAAGCGCCCGTCCGACCCCACGTCGCAGCCATACATT +ATCTGGATGGTGTGAGAACCTGGCCCCGACCCCGCGGTCAGCCCAGTCCCCCGAGCCCCG +CCCAGCCCCGACCAACCCGGGGGGATTTTTGGCCTAAACTGAAAATGAAACCGGGTAAAG +GCGCCTGGGCCTCTCCCGGGGCAAGGGTCTCGGGGTCCCGCGGCTTCGGGGTGGATCTCG +GACCCGGAGACTGTGGGCGACCTGGCCCGTCCGTGGGGGATGAGGGGTCCTGACCTGCGC +CCCCGGCCGGGGTCACTCACCGGCCTCGCTCTGGTTGTAGTAGCCGCGCAGGGTCCCCAG +GTCCACTCGGTCAGTCTGTGACTGGGCCTTCACATTCCGTGTCTCCTGGTCCCAATACTC +CGGCCCCTCCTGCTCTATCCACGGCGCCCGCGGCTCCATCCTCTGGCTCGCGGCGTCGCT +GTCGAACCGCACGAACTGCGTGTCGTCCACGTAGCCCACGGCGATGAAGCGGGGCTCCCC +GCGGCCGGGCCGGGACACGGATGTGAAGAAATACCTCATGGAGTGGGAGCCTGGGGGCGA +GCAGTGGCTGAGACCTGCCCGACCCTCGTCCCGGCGCGGCTCCCCCGGTCCTGCGCCCCC +GCCAGGAGGGCCCCTTGCTTCTCCCCGCAGAGGCGGTTTCCCTCCCGACCCCGCACTCAC +CCGCCCAGGTCTGGGTCAGGGCCAGGGCCCCCGAGAGTAGCAGGAGGAGGGTTCGGGGCG +CCATGACGGCCATCCTCGGCGTCTGGGGAGAATCTGAGTCCCGGTGGGTGCGTGCGGGCT +TTAGAACAGCGACCGCGACGACACTGATTGGCTTCTCTGGAAACCCGACACCCAATGGGA +GTGAGAACTGGGTCCGCGTCGTGAGTATCCA \ No newline at end of file diff --git a/tests/data/chunking/chunking.subreadset.xml b/tests/data/chunking/chunking.subreadset.xml new file mode 100644 index 0000000..74d38c1 --- /dev/null +++ b/tests/data/chunking/chunking.subreadset.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 933955 + 1220 + + diff --git a/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.1.subreads.bam b/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.1.subreads.bam new file mode 100644 index 0000000000000000000000000000000000000000..ca926df64fec2bfeaceec04e5fb16bb3ab0f884e GIT binary patch literal 1088277 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

QMG39f$rNZ;;dV%+$;ZsmKFai&*;(FC= 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�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

GOmV{SBxaqLr~*U57ZOl`qY6Al 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

m zudmBnx!li$x*+B^s^L~oDhO-2T)tS(?C(0ot3RuinCg93>qs^2U=_UgOST_{LlaEuYRtI5`d6x@y+ymA2ojcgDh0wK>O7D zJ(fL_lr^4NV}&Zep55aoTHUB-(>8CTgB7#I;<}!5H0b=b0bgXoyii@+|5akAw*FZq zwU;a={;NN4yOXqX+|bwk9mde|Vr}DAGTSL3b0VIX zYC=jX3By8dC)r&~N&nf|!LB68d?N*pJe2>izg|qf7Shs}MeajK%_Ne^Y-PtC{U4dN z+_&8AVrG3;E`Fe1ZYO@+N~W7BpkA#1Wrq3D6@s0tep*o8KgO_eOqut!O=7elp+^$I6`ps75sF*O5Oo?%&HLIL$6wlHEUn#Bs_lMF>^021t z{ity4Gu6a|4RYh#Of8%Gl6}=(&&$o0l1=0i+k0DLQee?qKRMWvxlj1?``M#$=Dq6f zXQ}i@>C~R{@q2~T*0%~3mNPONys<7PbL~t=mC_J4`J9}5XtEeeNW*BBOy`}JUEvF>UlFTJvsMpWggs8Et zpxCKsHK~?byGZnoDq~}-IjVh-E~?q8cU^w3X62OpB$RB>3!2#9WXf78!0 z`Bb7=lI+%~3 zC7bI1{%y%$L(i*7#kJzmdT&=L)nDcFdz*#EW0Bq zLRS1{a(y$&@om3ZxX{1)-fy$N{HKY+2W#9YFG$~H_V`@k%Pq!kZWr=SI+!T@Zgupd za-GfPl9j4ZSGRKvOhTdO3XO7IsffjVu9&Hn_+(FF8f)y9B>$MrSCQvk4v~?RWRcLsp# zzP=+QP=v{XlsaSpR6wi0*g};p<#$Uj7*@#f`9wa$mXj$dxvAg;`!|B1szsLPm|BkE zHq&WVD+ BDanuwpgUn^R8F0H*H-9DVBwAp$tSB*Nrl@CS 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�u%?aW~c#cZdD>8`2y z(eSsLfHV1Sp7j*S&GGP7A{+FCt=kiRE!wS$s0yc}kNTX>@6PYW_1)bZ{P|?}Jf@Fs zim1GGd-suocB;nAzxT(#@vn*h=3l(w|DB)x9)-g36X5tiemOY8H$)ELm}LdC?dtrzBUXX#Pw>Rl>meKQd=43 zcF>2%jbRwu&A?n4`WhN&+l5Y>tf1R<36u&nx`Z05jS1px*T#C=2T%mo-2x`+n%-X; zn||Nez;p)C-X4_pz!+@4=f;1P%BQID77}Z^^S%h-zM?!$Sk}kGICru<)x>t5I7pr& z+)rTL*G|uR*q8qRhM|nzPxf|u()-FGpAdpRJR14I>yMc6mg(Nmhj*U`!>=n(lK^=@ zhQHnWkB`5*dw5EM@)<&WuKQ=p*G}*K!@k~sfW_q}dwc)E^Uq((yN4&btcj8SZBkXO z{kku<^ai`%Pe+5UI92%nrOAoHxbu(sE0Jk(oS-&2oAob%{Hs>~^`6K}x+(GptzJ_UJFOp_?FlFQ`wUQO zM-Y8kRDYG1_;0^yv&w#-6Gd5-*cJ!4$}`<2Z|rlxwP)IEw(aOrd%vw}Y|BzqS=4{O zElS!^E&va9+T5#Fx^0GS?@P)7+h{N^HZLWH(|*8nG0z?| zY9gGE6L)@6stvyVM<fE(+G_&na_!gRKL3weO204e_g)+vw%sn%w&Sy| zc-SAcB7rf)fgu0Aw$eJ$`(p1MD*!JBKr_Q|Wc!ip+W?O6KMs&P9*-Q$w0#7K76bH* zkdF}=`GG^+5a`CH^n^noN?=R)GBGh6C9#i#5TPL^A&^@fnGqa~C?$meWdKMKz-1f) zr~!4wWQ=j(`oquznj9kHjG!k>!3PN$&Iri`f8sY$el6XTLdO;LZ8%5}s0RZA0yl&DeELm_sfrLx9NXa#dGLh_Iv<9hz>xL| zvf#imJqx;bd=vU20JhkR0c_(DC1y&C0sK$|tU>3<^D_^nC~^`MF2n5VJc;4QWZ)&? zc?39!^C+vPWEM{@N5m;mSY($$k^}h#$rM-9*@b(#@FP+H>g1CstS(4i;ly6VMUfLS zM`aN?Gr&G?27C;cGoDrxYc>b;NhfJh#q+p|0XT!mpB7ay_wy?D$s|dD07(@&shtoX zVMFU>3rLVW3vq)GrOq2)AP05MN0{7nV0i!mI(iUVNB=#3Z6swmHwGcpCX z18S|%aOk=K*Ao<7#nnX|ROb_*z)NCA$uRM9G|BUsU(8}FsIqE-{2b4sS$au|62NmF z#d$`~v#S*6(O9ahMlDauvd0VUbi5r$Q44PK9|jNx~_{GZ?dqs(BD6p_x_Ksm=j@BS2y| zn^sXsid$Cv-4s~ypT?hL#lRT@e4rgK1$Wdlr)T_I6nOwnaZ1r;b_Xeh(#s7+*6d`~ zD09a{R&d+x?(O^*&t|($qxumJIo2&%&28vta!aNZ$|xxX^#G1n^H^{@AZd9_8+08WpnXJ)WUtX;V1ftind_;2E3#u#?881>p*XYq3a7{ zu-;i0_3InsBDD{0ba(@Vw$U^oy5)MgDf`Q{y*b<3HTy-}toz16|_-XU&o#-D``;2+;%Z+aDYW8?vexlt&6nY+f%I7F`YD3uTaGjB2a-7ccZBZ5l-DXuq=xdA??Tc1}8EA?k@(eGl z`}8kTbI1z~z4>y;+mhb$OSTgos|$g?Ol+IgPml<=7j?Ei-vp14dwsA0)c%B2W z>WGa-UzAu;R1Ob$PHagBTC2&B#;K;adn=xM$?>eF_C%(y3>c;%@`uWvf65$j4G@fJ zD|-ybbQ+w{lmIvB1fmipK{R5sk>@i%Q(Z#;p zGxkenz;+d-+sKt(qbUjOK1k7$I7Ss1K?a6v@gn=OBXy*f*y%M{rpvP&BmNfKI%~Cn za)FP3UzUDF(S<`{#3-D=v&}98V)L9N)rLO66(_8@3z#hmf!d-VLcSMZWCP9+Kp21| z2fzWi%Z-KsRD}AJBoKCi-EinbjnIwYcX$v4kv9x{Yg`gTHJ~jr^lgksz*$iQ7z5yhu!BrD7`wnz z*cpW+^5JKG5FlVYOhtn>QDi$|ICiLcGDahU9d8s7L;~z1giRO)hc2;^3q4pMT;u>4 zMy>@+2u$NGyO_7(F0P0CXD!BWPy2AUO1csCFEm%H|WGycko< zv*}>^Sl5Waa`NCxM?#Y~UK-DpG>e9EVi`Kvv-JqMA&TSr%W; z&{a4FI><LRk>qURMgj7D=H ze|MT^#quhuq6jpJswvPLjzCZN7Q?1FVAwxOKZRkzQ?{|2GArhHxCOucQ))OukEmmZ zKk0)u**x2skES(acoZ-^L|bGJXru<1o6ci6W7-c4eE7}^wgZ^xzD@lSn$0o_ToxUk zVp)7I4&L<&?ZSNSQS_n`fYj3hQ;HeaUEV+q%$~k8Z{&GgFs&66kUSjkX0~Iadh+@1 zNUfI|ivX8q=z;BRHwLXy+|<5NmRpwkTM zw*H4Nr>z9%8PHZns9kQMYnoQBm*!%-S?SwrYI55eo7yO6UT^Hx$}pFPVVm0}K-X#o zv_lPbHoRDF2U~4xpKUh%WvOp$z$a>xJ6o9RB|sd!-jpibWIw3z*gN!#Ju5#1wa>by{vyhUgWOAN-@dh;u0gfnJU;t*r_HBG;S-$k8I#uY z=BLjZrfAPkLCix8y6@!umvs5u*ncY?pdV`L-Q!pE;RCrIqU`%8>~8dLkI27#p>yqS zlaV_T^X7mrd#?luU_*S#uuQYfE3(YCbfzT;k}P-R&OwLe1x96it+v#7EjKu|@q+2L z^rqMrP8imcoz5i@G|>=SY?nQfUL7(g!eNal-zj@M(?Wc^*>AjBvi;fK!K=L!u^|}Q zeuEP`2kdM1+Y_P1@*QeYd!cE3_kvYV)a2v`^4_bS3jigFhb>v@FsXPXdma8~TBDg9 z?=yTy=?>%raeq(byT`xEF=xN39;g?}__Wd7dnNM2mPk11TeaD39PjZxS&*9}IM62oa{4f!SM>u9yUbb9~fhq(Hfa3zZ8@ayT2z1hez&yUlxzsCkHUiHp^VmOq^}y1dvq=YS{Mt#*?yn=1dO0%!F&&cyTD0NBfS0I_1AP5?R|*o#Eeu!fKq`7u2_^diTyJd7O&p&^wrj6JC3xd@qPIHFWa zzq)`*ftFB2d+>n(gAl_zI`<*Oahl; zSRDAoi;zcMGI4AJwIUq2C=7rVYikvTKjl zh?ucQDQ=F=@tdfs#(oveBg?v&;>#)xqf0<7Tvai!R&p6w;Uq^%fRLR<=sZj2QSipc zRY0oQ0vA=5Rs>fU*#$*E=q#HSd5-)leT%Nrx5eBGD!BR;P|igjQ?ddWsxBxV&EhQ2 zF|bR9^NXyytlnM#YNwMhE-K&`fGOyDKA}FjS)4}2JSp-DE^_Yp=_K|1EKjFXhXApK zMVMC8bL#S#1@I#obXws&h|>5xPw=FoOrEB1vuvJ6`TQ!&l4|+}ZpzqCk}%6EP#K!1 zNjjr#9T>c_=8H7Riwv$`hP==N;v*HA5zlg`*(}d07jzTA)rzjF6wfji3l0M-5L`6rEQ)A8K(0DZEZ!HU!d zoEzJfe+yRr{0`-2w+t1UH4ot%rg3koApF43@Ybr9?&?r3@o(6M(hdcwF@TVl*c5Lv z=gx>n2`I1m%$oTCIFUWKyt<#s4J_qBZCiTe3rWYjVZdl^qgyA^`R?c~iv~NS0@U)- z+QAXtV`s--H>7FJ$L1}JJ;1LAd`aujekOEK??whXpP6^>)jFEr!s2WI09t)2^FEPuSFcz56lc{oh|fd0AHc6sI_wFxT38 z1?*vTl*{Gre<*sXuU1=whRQA1)FHBt;?rml-%^7U z+UnXUfg9^6zV&KR)>g3oY8S@0?w2c#THDIC4XoIQcDk|HYCB7tc70tAu3@C@cDvqa zc7JIuZ^QUDhPI~Gw(C9(usrR zK_Ht7rJF#eOXwYdb^EZJy~DxEcx@4r;Tea zdBj*Zf;ji$eZeH1T`T8-6Q@nAC&n8?9qP(y-;1+*vhFJUjcek;0Pcs!p9jo`{PXS$ zS?%2pf8M>nqontbdwT!318>g-9DXPZE#>Fp6d(7ot5e=gZP(BHC$vMoR%zvT_x;{A zy?Ooxd(VDc9t`kkYV=J_r1bBk)Ru+8VUuU{k=s-NDW#6qRD0aXp{xr0kK3)iSA2sp zI&6n)v$7Pv_zi~PScV$K_WE7XZ?-QofjiOi zjA`*glNW^kBxDYIW}_=wQfp6=P${wpWEDvDY7&;Q*M;N8)n>^c8_qR3oRX8xu0+y7V+$`&u4%ZzXThmAiP zNz&P(Q8It$TfP5>KTdvAJv)&8uGBtbE{~Wa+@6dN8+qf8+HSe>T6?T6mX<`se<<>T z@deW@2%KZPcL|`-Npa*i7E(9iC6c8z9=@?-k59h zhpNhoEF<;~Ir)%Rb>Uo4xv#x9D7lt{@CyMTh!*Amb=9z~Jwn8OGUsqd?02QWDChaq4sa;dEpz;%d1 z6k*#BeA}Z~OJKS_u;b7I!Vbw0ArjaYB2I)z6byleUCTk1=MAl~jRF*!{wSa@IUHN| z*mN!1vVd|O8->FlKzAjT~4B$78iy*$stC<2rw)f)_a2}nw^ z8J?kV;ub)pFcWt+n5;nZUdgM6OaVzMR|B^B^NpKFjj+S@E_21Wm3c zQB_1`k>rzT2IM@gU|ym3ma;{h1yuqU4`(x&$|Qx1lP9lGtprVRt>|;7!*dTQ= zLuokly>T_F;^Zo-JizWzG+QQqHBBeJKf!U8WN`gvD1nzC*2O5VyeV?hDZMz=Fb<{@ zKQ4S1C^>$cRW|k!K}GC?(jvITepq=if~$Q8$>j_n`A3saK{9%1`P@+@dBkFOc13p_ zK04x1up`k2L5yEeYV+RshB%WQ?@@}pA?gPx819&LINecZ08K~EEqI%Cg*zaf-gMy1 zr{1mi=-9feNok%!sO{WN&zt8(J=buDr-$29I(i(>xZ`Ou zzqjDt46`HX@ZQ+DGmp;hXPHv;Pw%Hbs=+&pcB%>C)ND7eab8PCsoJsY7Ppf}!A-aI zkr7Cf&hGeDTy+m>N=)z+o!x~4%W*h4QSkM2Q+{XhRX^|+pw35!PXe8RwiZW?PjyJ&sKoS*PAT>?$+L3U)$w1Ks7-2#;^w)4FL9RrI)q& z6p&l5EvPiT&UU>8bYB|=jcQ!g0gVe|rERv?0Ny~(D;m;h!sE)`ZU)=3+)x|pdOO(a z{WajVMtR#bY-39~-qsAwfMzQIf4#43XJ)xw)FF+Uc?LagS7&;EtHE@BISBWC`I{-9 zKx51My3{UDL+BHXY2DcWh~w<&Z2WkjdrPYQtk>w5yVpKfzIbldLu9@wAIRl=$hLQ# z-}&U;yZ1gZr=N$6t=plWFCQ}R`||6c^l27;g67`ea`3wwli|CMIqc@uvjY6}aruie z^W77XlkYyN^33@=xGnESeL_z^&urd*zG)4!^v_efL-Eyk$v67F|EMRuY3tmdD~$ty zMWF?RB{>K3-(#Acqh6C&X<3S zkt&ESj+NRp(D3Ns@JQ^*rP5W-eoGlhCTbiqxqjN{#Vn)!K;i~!XVCmZQ56;OjmXO- zFZVc2W?!`qS~}By!yK!oBpbZSzYtHwZ)Cto$vy1!fUjA$(-OO!b|^8-x8F66`x2+~ zlA!W?N`r46p7e&}PDg2LZ9^O=z1PBtFLpp+Sv;kVzesgB;XqvU`tWAZ7unzJ$ej3{ z@F%?e=0%4Qe$wZS0~Vw>Wu>Lcw_N!p^r*{v5 zPaDh;EBugsor{hCgl)4Ciy5>Bsx-SSt9H5qIaW&z2wm@TJx*=0f@U~;vs74S$OEPN z-jHTvu~6uEBV;;mWJR_Y1OW~sLQrIS6z*c|yVNPxialy?bZMBKMUf8Cgf_-io#HML`hMsSF z!(e2S*ac7mpv7bA;~N2HV<5<&MpO7ki{d(=4|D;u#DKqeNP;2o`xq!4+dB>>e&~&G z5YcePfTFWM#uUQ|8Co>*aA;C9G^W{X0PX$AasY9ut=gdxkuVoDMj?zq0*ov_2KCqI zPTh=QWa!DIKDa>P_K+si0iH%t5RRxr?GW1$3d|4_#{=x9L!w#_KIn@Yp>b_;B^Ab~ z%CdMm4{JMC|+PZ%L`o1ahMlZ;R3j@Dgb@w z_^O&^v2zZ$Lz)$nstQtqP%^K`wD18>!=yr0wU~u|wE%!D;wrADlerrLB}V{b!L0IO z$cwZ{s|9dv0q7T3MKuO_;Rej2;+r>lH3}U+tIm_;s>o(OO>2`)lGrb@EExqBz+Z`~ z$t0+X^C|)rk;qLe-<`Snya>`+mEw4Ek-&tKBFd{A*gXfJt%5MVtg7;Y#7ZK%|%nBDkF+Q83XflJ( zhF>L@xd{@vpeG!{)DU?~P*BC_A_eJ#@I1taD)P<5@U05mg4T~m zyW{ulyt9Y;RLWaa%x-$AV-}OzDt%M#sMm!FJ3A9>l-%mYLU;Du`_M*^%7u6In{j6j zc5g3BFpmm*PP6>n26CFt{5EW|?&l+5{J)Mr2FCw_|8ii=qxh#7z7$gCS~E&&hXu&1 z&9Lh=;MZmV{I`p3EK4B8I)Um+H%gu6KBZBM2F+GVLk_oFn(C%3HQ+NqKj1dQ0LrBA z*K1v0o2yczHrKQ3>&+VIaa|f)sIt|J>qURFTpH``*07=D<)h50i#l_vuE9u4T{qVK zatX5N)Z*GVOMAIC>*T4_k!PrdTY|uJ&TQ2n_TTW%n=}1Gq!83)B!4&`T!VJ zH=uWorgUBQYf84)>(zE`Ttk1WwNB@;vadIb!Fqjtwpwo1D^SUHv4weno~Vm42)$YX zAupik^)*ndruSFok^-_}m^A4RVD1)37_fT)f(ID z#V+5^(%7zQI^G(ZO)c9n65urD<26kwWL&SP%^dn4l)7Or`Y_@3!mvRe!05FNto+Mi zxbMsN<@@rb<--+^zj0sb55sbw9nkvd#na`Js|D7Rug9P6)Ba+Y@!O@FUs%%LhvR-x zr`CNkDC>z<5BhWMXEgN{!v9?BOwaZIz=Pt$A?gF;2mT@tYmA?`I-kB?&x&o4`}^nS z8MJBH56?d#|7RAcJ`+>%ac%32cBr94=uv@Io9lYj6UKN@Bj;PAAYH(_kuzXYC zIELFF9;qVNQ#?r&225Y(euL*_m;FyQPUrVoUOJ7Bnk;wx;*ix0nN?X;tZ$avfi2xFREUjZ;qKdq-+t>`24(0Evyh`e&^(fs@bP2rSFA<-Xiv8J1_%aIeKn zO+jRYqmx`YX^J9yYXW}9ywsKOCyPI{Ka3NO11OotJL4lf>PoH$|yaqxowD?wqpirmt4 zsjcw`&>jCm;Cjth{pP+YNQWHFf5)giPji~H9P{EY+w!lA@*#KhTI?|ga20-_DlEgu zJ?W)UVy_Ms;8 zjKs7&{#t}R~W8uBUAK&|~>Q5D6}PMIHzFn38| zPZi$yl|w<{8bVX|n1yUX4ZeBKX56 zjKCc=nlJT$|4vnZ!bvTK6VLZl`ITrNannIVO#^p)=&%h-J!+pxhqAynhQCja~FD7=qbl1T&l1KGT)RLLu!i$(uK|niF67BTFmR$r&7ac{iLk zt^FkhlArN zBGHg83lkJNQS6dB#W;>@XD6r;_=K)O!$BHg6WFFp6U`xl5l!|^6G6}l)bWYn&>gzA z7Y!rg$8|JN9di@Mf#=0Em%}g$oe@DXf@2;cRz#EM#cpIG9ECK=ydNVQnj!4qfFReh zX!1YTcik|;@RNitsAJ?geiV&7J3`2&QAQEX(hlQ$ehjn6Azgs>2zF_Xav#&o5uqCf zAZ+Z7p|%}@>O$fNVTe%d1~fH2$ZEqskS`>bS?6oVbm<+to)ZM2L(}+$)NyPC3X7dM zqn;vaKpn6`xEdj@J*Pb4TK>o%243X3q341; zV>hB%EFw%N4dVL5^(+U6B!J%i;h1`*g}Vz)wMCQu4P%Fl$cScx_i1uF5Ez=*Y3E}y za-+z{$Q@HtMHIQ-D58EigbZooK^m471u(0~HEFI10vZh9{s3LX2%a!9sRJHCa4?{G z4dE5_y(4~vJqHaPD-10J>Z>zr(1Lhz8# zsJUSr4nf&Lh-@o_W;leK%=SSOLu$2%W4Ma812k=w zPW%F0&HO6Au#?H8ns^ya#Xl+hs;Z{>BuQ{k;R>hcILnGEBUu%p3zVE^Gn|i>RWP5R z$Sx+~G%d38D6J-;7p7O!8A+=wzR03C=krN8n@3&}rfELAO5-Aquco93r`Y!<9s)_y zv`Uh3m?o%*Q5ejYL6(sDMLzK+p)<*Lp|{Lnw}}|v%M81tsE8Ly6`g}DmkFNDX|j?Ez7;AO2!qE7OePHT zFhbrujl6HFS@NcOlar*V(!@!VYrg%ZcSOmR^ac|P|qZLh$SiJOIR z-{1+E*cqydY#OD-MHND)X?||QKog%7Zk$voabRj8DXuEBcsqsf!a1%kbNK!QU8IX| zqBKj(DXA_m&oAR-dXa}$`J_VUDJE48cTWh@n&To&--d4|&KOOT>Y{?LANc%dvt$xf zmY>I2H9b!ejWNxqc#_0P5lzydBFL-UDhUGk;)R({;~*o+th%h~O%75QTS4JwlNcp) zxU=9wB-jn76ZiyQWhg0d8e1qTf}~30^U7c1puklEpO#S-UsQP@g?E*}7c^+CtddJm_zZ-M$gO?o|GE0vpZ&&fo`1?dMJ*z$93a6D$d=F7SA7-eAi%_+*o4J zU4@7CAeWBpQK_t*Va49{MeQV^P4_M^=eT|clgO#}AT`NQpF#g7(yq<}1Jd5fJGn6v zne+MVQ3A@lf^WPE{d)Y{yfNNx&MECNy0IVOo4%;*J9|}Jj}3Kac6}J#C$7BF6KzuK zg{oz|Q(Ra#Cp#tOFw{+(Xuiu5^I>+FT4B4{q>nbIpxZ{=yrLGex?OR9wTAY+t;xQ1 zo-E+muWQ^mQ`Xnoz0(pE*feiEI!Cv*u!q}hxb;vITz3{vi`)J`Ech;e={URVBXVyI zZxhe}^*ps}8OQUFx*6X)bJFP0$2)y|@Jvg1tAaZBD0-C4#=V(^6@S=jH>_W$S*=@V zQFx;de48EUE{xNyLonyma+=IZu&d|Q^1)r1p`DK{bv3o9{JQ{8dspXHeyetRy_st8 zgw^lx2{+My@#Su!8GH->6zA|ufhIJiHa~q(Z<=_Y(bR+|x(lJ*-$h%lXtX69Dp$(^ z-7sw{pqOmkq`evX}6V;$x>8qty$63;>rv00&rkZv(pk_a9yQr;P+pR{k znws|7G?&}$YP+oyn{Ec%t*KvYv{P-V>w~SP@9chbJH^eqw3izYa8ai=)z{j3YZ{w6 z$`UFJ^fM567iYOKH~+yeXKnxc@;6Yv!eC-OUYY;&s_rwVKkEL`O7ZxM7Me%T9Dlql z{_I2^j(F?)>3prl<38^3!y}(<@`(zL^XTnI<;i9B=O+5Ob@e+h$tM>|KeM#_?wMNU z2XDS$J@Ppb-+kiUgYsyzikrNq@4kA=i;raaY!9EE+55-tuus%~a*XE&u9siwAEmu- zB&H+Cio!P8cJH{Qa1FK5R9*=x&%MZ5f#ao4x6kx@TvuROhiy0an#@RH8cj`VHjbIj zs~3lKV?j~a@AR7-*OX_n$Z@=|#~peq|CirNoQP#nX1M+#s}B$R!GR(Qa$kSN_j=+U zCzi7g*YC=E;bA5OoTMBds+_j`uDRb*)ix`z?LFS)R6){@WkF$x$aAL1$)TXD z4P{Rh4W&OuO-I@1JE_}x4idx0ZLaYLb{$6(S0ZCMIWC=| z;o@*SjtEUr8ryWK5JokDha%5*T4f{@S$rOS7;IpLkveYG>&{^p@4=xMp5MX zE=@T^sH>{y4Smn|ts#x@48y<<0ounwGz>=(-3Ah4L=(08gsyM7Bt!_t2~6LnZl*9X zI|Skzf<6Nqxi~PxkwcfQh>hU~T~Mz#(k&Np97G;;j%@_MA2^7F!=Z24?l`EIxh!*x zqQG%H*BXy7O?!(Yx|lOdXQ>~0@FTPUmbVK6>haP^MrLVJO)|P&;%s`EEQ^bC>bpxS zK+JhC4JRZ%r(0D3c*kiJBr`zLX>vKuCqk}h!j)TuILtwMFvW(;&BDqE)qYC=)%G*JJ09(JFh%P8&j0fce(}8*=v{W6yJxQknemQRXp_1#N5rukNpwT z!j5XSxI1rL$FJ8q@clL%__13o)pU;Fh9q=c>jSZF)i!?u4gc#WvakO4Uyg=3z#*Vv zhB344mnHR$yw(@H2*UMhd#!EF2N8tZ$uxDF*xu4x#u|CWpWIa8BFX;EK z*?nB#$0%{T@53kY?qMdGFWcSzGv#5v)Z275k83=1xA{t^rmy#bdbY*8ulF=6KlIvq zhIzjLNbkg|Nss=GkrcZv_4@)q3oD%*9!uI0uWTFgxU03qmdJNrAE=GCs2xZwcPh$4 zTapc(X#%XVN46*q*)yi8Hd=&jz8>@?oh!wclI%4VzHhu3SzNbqdf2#_84@=&@d8+n1L_oHzQw(G#Y%!aYW0rz z2B%AN~Zf{Rz*hQx?;lgUf4ZJlQ~o1n)})-{zWLcUBt7;K#VMCi*L4^moFHpb2NNC z{;yOb57n;M5Nz(7Li+AlQn;WYvZ5|@UhgxK)aL#>Wv~6R$#oiMjG-~IJjis8pY}Md z%_vHz_Jg9s`H7~!DT>Dz-!bNj)ydX zjZe44fFJK;fG14t{~@wmI6`-^sIy7ld?Qen19FSp5nvA85dzMRY0eHD(}Xhq2#*2` z97OCwZj7$T|iKO2sL7pxWIzQq`o0^w+!DO z`gCVTj6IsiG=iUIG&m1~ST1sWWJbW51fUhg7TvFqMlh0a1Y<;?EO_J5jIATOr6cjY z+MOY+cSDSc??&{A0K?H8MyT3D-*vDTPP};lmE|8T}+&ij%$S(zM?zPN9Vz`n$Bk48&E@n16(FmL^lS6Sw>Fep~}mE|&ZtKt)p&&*FgO zRql~lwaBJPlvYKY+9bn)pGKt2=U(ao1t)QF5yG$PNfa0HJShrqj;wD$BOxy6E-^(0 zMCqoJBF*ra{>ZkHNtKZ}oK|6S%WwZ;3H;W1^XZ-KYZS|XJ}`Ynb}-|AXjFCQ^-dP? z9hBYL8h0J+?2EHUO=@7N6P^r#^KL9;4-=S-<`es|wGSA0zBA8Jo(bs~7N!;NO?7pL zAT9Fma>3k{DXt}*Jg95UA6wu?)b>VY-8CKVj(PXn4Nm7l9`9%>s9V;rsZkEqlI?cC zxSi>}J#q&B1@k&y&#SB4Na2__TWZw9&Ti7xK7zcP%?clwAZNFxP?X*oRp~IJS_Fja z@%)c>C-k1!olyL8V#|^oj^HR~t_Mb0Z%?=!^mnOL2fG+PN^dl5uC#R;!3R)9ZD}_< z6mAxj$F_ZKqu1F}cP72{)?U&mK27ff(wQ5exi$1nL;kdK+uztWO`fU^)*GX&?SWcp zoB>;zX1!D4_IjgTulf&S`Dj4gHK5<}HkNN-Y|lX0jkZ|QD82rsUk>aNX0R;Fb*au(g!8-|$uYs#yA z``Q4Cr4fA~#Fpw@J6jq?c}6qd^y{F$jeT~e8+7XvI`#e%CS7WvsB&wUyX?7(I&9P2 zS#aT6z;y;`sd2Qn-|k{IR~o&9gFcA49Z-udHR0+upfS+%^#*Pinl2aQp!-r9pfP>b zUoHDkd$GFS0KwC2xu7>4)I@_2?XrJ;7rJSjt+eHx4Hr;+bG8M_ue0UCH7^&&_F5Y( z>J2JOx)El-v~TvPG?t6ffIDId_bx~b%3t2($?ezI`bE}C_7@bK|Ir1ozOeHTzp1`no~K;V+~+m*FlFC!E6q=Y%l>WTnlEqG zpMTD%+$Y!6zbZtz{6t5e8T{EQA4kN#e{lA@2R?8g_IJOr+sE1GKODOJu-eVO-sQ7$ zzJKQRGv)n*%!;4bo9^9{U45Jk@zdqqhcC;UB>!KK!0>)D&*}BiNY5m!{P5uW$6Y^= z$#|X~}G(-{e{yrLBlB_?E0lJl||Fa!VSqDx(is zf#q0qpzf&#&mD3drpb$f78YnBxbq(ip(C;Koq zdno%Sve6LukQ>Yg2R(-AHD7W4*Udf>S+&VB%mLq2?EP2LQc@&V>Fo1Ut0f-@ZC+Ib zP=~0rTAijKX(rQdzHBt22HRlw#s1l`bi{C6oB5I4XfVe|uQ;i7D7B=cPLq+R0_cy| z52jt^8?^!Vmtp8E%dm~}-;soaztdtHk!y(RK-%Luk>}KdA>US5p~d?G-)@NucFw3T z1y$%YC7DlkrT2pA)6C~qqt|Y#$80ZYcEm!~7@>E>wI!vY^*Di7xWk6@vV$0zX*YU; z)Kb*rTxqHYO;J$xWVF`@ z(m-wWCal6}2W_EbR99y>MtIedTAh;H7x{f%YV7k;1Ha?;J6(nod&+qKkl_x+rmP&v zd%xLwee4~x+-dtr(1q4vhac+}hxDKPQ2d6|^`6T2#iQn-!171UWpI=P{65Q`wcbka z+apEcS-7{QJx17XGi_ZsVVDNTca^s7G6Ey0tjx(=gE>7Fx&E&arKw4L4@T|^N8E`z z6pyW!Z2O>b)`PpbCAQ;MXMc}VbVhVqqZSVzb@(tb{T9E^u!f*WAuspTc8mRo-+s$A zIuhR;u*XVQgpW(B<9%na8ZYr|L+DC9`9QMFy&o2%{=8v!l>fKAFKKQh$R!OosOnY}RNx+x)o<9%3-M{xet$$*^Znh_e`l@B1 zs~dV>nRfL~Yz*tsP$6&YYOj0TIH|SjgH3;^b~}ct%wRf|daM2InI3^fbxp00TaiAf zcTNoBRMFZ!rJ=XA208A$Qq7|gSF+>ADXsS!^>O#z+fKKp8hzCtA1mWGO?Yuco9bIJ zF}g-gYpcj0p(um4(Hkk=kUE|S6`$F1Nl;WTurOMH$u&zK7p zukYO*XglCx=*=;bUGO;<;mk!61V1D+Fe|(@b)XjyQ-sc3OlmR{#0)Iv6W^mqPK%?3 z6w`(Vq40d}U~*N=H-i~dF}(|QP;NmvL43BD%`gipbOM43-*qt9-4qCT<~BzJIo^)b zFc7l^53RtPhn{Cs%z!$BDn8?;<(Smuu-Rk_5l|ZV?hbE_U~Z&SsQ8F6X$>+OfO5FC z;hZpz1O-U-z$xO&nT>D;2YLiM%z0pW6m(*~<6795wMUV-IpX%+S6zvKX5IW{e4D-rR-8Fmp%{;DG7;g=>0_@3}LWCB_Kz z=ghOH=OUEec7+QKIsRs$sn{HI)KE+V%S=SuQ!t5(pof6Y5H^8q3Nta|7AD-8vw#wt z_%xVTDPNHoqnZ-Fz-&7eZ3WUpaK2+msCdgL;jWkoioDGMpMgd`705O`3kdFkF|V%e z39uDKygRpvFg@ghCOA5wJ_!P(Y<4{gz6ve?=JExlF6O+2*9m$k(gxTd7fkgmM0Z1e z4CH3O>^!2HVak1^WC+1`Y@}yKq7U>q@NP~qOAxULSO8fSFkpa%3kF6;UWECM)4;<- zwD7kNqgv3r>wyVf0#kOFcd@6yPii-Q}9<48iV6fTtOj5FCZ}lH^UIw z7-q=S5K>FP>hKom>#%#DnZ!a;3E`OlXh4_0%n1V5@d@#Xhe?$d3kMw9XY&P2uMl8h z$}9&2GdZQUA22VlEJhvhtZGUY0Xk%52?tDsR1YqKX1oBi_f|^@>R|4CFtWkNPznT#_?Wl}-Uom5922}kU`}KQj8EoBPz^nX@CQfcY9DRxiU6h? z^CH3Wh6hiG%hU;oiG(AdF|)YGNd*St0dYL=E-(<{U%-b&U=g;kkeWKg=ZI@kSpUe; zO+6<-m<+OYP*{$pm=Q*8cLqXv1V(~YGdDeOYd@&SQ3$mV4HSkjGQ1A{7Z74Q#GQfn zP%tpt1(k4cj1Zm~n9>;|8*s@8n>#K?iToBt=S))zuF)&O}KPSBkZ} zgoJTSLlCsc8JAv~heZyvE`u}*S(+6w$U|rx#*7z?UehHHF3+=zf<@t)MKS~XM3Lvo z)jTV%@>rxYL`I3y3o<{1zC!^LNGUE#k*DAjmPD+Qyh!bkND2=tPv++^o5BPQqJ+6J zS~53xFSBBqW?5pv49dg~Bj4wCK$n!HT*BHb@IyrwKBkV2*fQeZ^GlZIc_}dwR?63L zz-i=%Jh9~EvXFTag6whu)5|4cX&TG3m`W6A{C6D+xC;r80`H!qkz)`Lew5J>p2d$iybf zKnf-^5qTn(vAg!ce@G^mmr0ffVG?WtFh^vk=`y~&SS21jFvFB5QCvvQ67VmY2hk-s zH1fZ!A}$$2Qu?I~NKR5(B$7mNBH@uA=8-IxL4eq|h{TcfT~=gC4BaP^xrrm7trx`d zJd3lCSPPo7oWeMZRLb<6;@2MdUm9dVAw%Dhfv|$axo|JerMDCrNGN3%!3w7-D`YIA z%t1b$^8o4bK~9*UoRv`=lGr=HWU*wlNK2ex;v#!I3(_Qz%)5XO(KydV7{U5a3mz3~ zNeU+e>93ZOM~RORJ1KJ+r7YZ}OrBE?%N?FuiNv~d2F8oMn1E}gS)R+llRQpx37<)^ zCw~A{3M-*J#`q!lKTnW=s7UBiTClWX2K_jz$XS+PfJo5DT?<~w70gI*k%gHjBX~O! z=dh}*A}sS2TVfKljIl^WbVFe(%fea4FVDl_;vN`3hB3#}}L&)Q-M zDt_aU7>9FILd-az!yC`q`AoIk*h*Q{p7B6zRN(R{2uOAa>o5x!)zeWPa=< zS?cjTIl%7z%ddX-```Z0>(9aN<`tx^!hIbmHmtJr+&%ex1%-R~&3TTi+rNzgNy#CF zS^V&04@s-?dj~tt5JawF+)o@;vEvA=sQ5MJ<#Ms-a(SSaZ}sNNHR-cI;2#C}XCEZy!&uLfvmZLM_hUTZ8j-!DLMv911{fR$%YXm2 zUHxn2&y9t@n~$jr9^>w!N9^Td-+)w8?m0+#5>#9!=CVA5vOQ)FJY?}Zh;^8Z@L|AR zc}S@D7>%~$wWMc=qyaSPX z2kC-REFOTRVd+BEI4@E%+k*tfhyqE}e9? zm#^5F;SiDdlt5=6iTF_Hu9t%o!>@}+Fl_qZ+iCf<98wpee1VUB@M;gR)bc4*wFN_@PWpX6uU69|>n ztm9PMPkY-<_{bbSl;M?xGi8@xafAsnw%7Mt zdpq84hZA!$x!#VitJD$OYeb!5eB@?~*$lU5H{12?q{^;%yWMVY*7xi2{d9YKH?g7S za5@~{jLj-{#BhS~k>klN=2ondN8C=PJH%-fA2}Uw&F$UvW^%TVk6e$gZ^w7r?cI8E zKZX7=?ZlmZyS6L9DdvxuY;QK39pH33y}zAKhNIEe1hMS({q=B-DHbto@^-X2n^u96 zAO}dc{<}dB{h|E-Dxcu8tdAJ^zk&q+XJ8OM?cvEQw*4_=<>$sXegO&cLU%vW;$=l% z28SJb{SwCHbL0KIN|y5s++#m!vUm>r*5>rm0wn5{bDbl11x-H$3L^u56_b|uAelydfvLa&&5xvw$U3lMy=JXJ2sBh zZwCsUo~w#ptJUi28|_b2{iv%oI`3M&_j@iH@fOc`&d0`>WVRJDwEf(?yr?M zZyK6n^hx7LZw))IR86TJeVDYB+TgU;GObB%*h4yT^R3!ywDVWWK&>n4iLTa}a-96< zdS7jgKIrOkTh|puSG7@Huf44`3@z2$z0>+Y9o4lI-dVuw7n-KMs~gQ$x~dEaaqy{_?A z{YOW=mQt&qj=Iz4LOX7$-zfU2+R~ff>MiY?ldSz4x>eNXw@u~4hpCpmd(}Lly~e+6 zYD>+%hFAKnb6_FSFIIH89}0>&7(JhabIuk>D}%Wdg=xArath=5`y8_o+AhX^&U`kT1t12i zsDMJ3;e{29=nw}FYN?<``_rFe@Uly@i8E`-*{)}+ugkI=YtU5u?8R4-Ed2z{#6pUlrE5VlbrHF!HNfL}k#1kYt zkU=Dpkcn6>Ws!ctr&90Nepl0`Ct`HY=##eI1mNry>BSw#4SfMIgsg}(Fy#$_hLM8>jQrX&kM zfFQ|imQj`_l8RV}jHC&dNs=aM7$G4q_X{HOSW3nV(1RzkNK%>ekVue2`ZDopY&(fn zu>3qh>o4C5cH{$W=xi9{7_`m?to@2d{d;CJ}PM?X~0}agd8(75Jd43}hNghstx02B~9nKZ%8# zCaWbZ8`vm9BbWtQcoB=jl$ddm&n=$HP_j5hN~7wu>TpK%pML$j-~aY+fA#s$%xXW( z^3p-Z*XS8_%VXr@^TU$;=5(Guejm#a$uK!Y@Bpyxsn3@sMQEOG_&~Y*YQ} z+#)Iy+(Qf487@9*UhT5D|8(PpRq`?l_wrQQE-T%f!=JlzkLtt#hA18soImVvtw-T@ z+up+=MAhq_A$LbNl;GKnzdKrZ;3#6%Y0UmiD{|Aa;*8C_O5SXNO?}*I2G41A%yPc0 zI(802F6O1>JhJ!jorLD>aPslV{_%gj`E>vI=U<<2F;AlGF9eHW|9CguBJ=7UlCNUu z-uCteL-*_|TJr{z0It{LDq8av$yaZ0$HVP#IJ{loj5m|%1hXLC+}_^U7_N!&d${E^ z;WKYNnXGTG?~(0hGBvA+O>DZ^+BX=#w}$=X2zHcf*a6z+=xzgB#qDH!yS3MMH{jQ zd~WWZ+Wbpa`RRWCF9I$eNWQV?}M9Dr&n{n;5-+&~DTk%Ana9HuZk9+kV?_YVYlCPpuF9*Wajy+t8Ikq`pzL znq{=c@7^{PB&Z(NlsCq>|E6ynb!DvA^xDbatn2!#iSoM9|EBdDqjzj5gHEm4svEj( z1g)7?Z)?W855w1u?l(QPrF}S8YR!?}9QFsJ=2}16Xdh0SP1w!Wky+blC@r;BYuD?Y zwLWT2HKVDXv=_>G>us&2zt;4AyQ4z)q}l7f{jsI}Gv!E|)|BpeqFdT=bJRRDPI|TD zlh&fGv|qRRH~sG9q&9BVddIyZV`hAKtu_WmxBL2})mPL(eXKQVZ;mILtCIJfJ_s?X z>qpIIeW?2N%U-uu*YlQAZ}!^tBYmo>b=_>9)MBlzHNNeFe64{pR=b0Z~E%+gVER9b=5ekDO$a&sCr%N)*9`a zc-?=c|Hf)GFfyh!YU)R|hIVWi^;%n>t3zc{JL$n>)r@bnkzadPf2*{$rlRP2x&|jmB1C&cO$c+6}*Hr&*Uz_MsH3A!*)wQt+g$^@qKNeOvK>w?R)J_U+ewbUK(H0#mo%7+PN) zwc0(crSxk3zl3j!vjDNE9P`}~Rv~41K)i~Q9J9$0FXX0OVPdg{i)W>XiT4R2)G4jN z*&_52v&}j6#R3mc@z`{ZsA<7GE<85le&8XZRUmh^D+rm*xPw{Nco_PK&J`4i;^qR= z|G5IO(8Qt0Wyc8#5QESBka(PmV1_yTW(X}7+@uc03J8Z?R5(*SvE{<`XTo(EqQ`@| zsQPe3g&3|7`Hl!2JhSBpg`IowFG7V0brDS+AbVUGP}8Z9-JxllR9MV+EOQ1LTX+H* z_^djYbt(|DPaGFR3%q&7u8t?fIG9I6OvlHVU_P6ph_vGRgSS0y1~cC!@FjSTqrm7U z50LZR^Pv@DzXR8?d_1V-b3P-k%>th=Jc#u??s8Kgg`h_fI38jSJp4+GC)fmMsXE!E zlp*9d@CZyD#vOPzo+$?|^%3^Mj0%Lb2R4}@(;i>&DitKc!v)4VVCVoM$!CiILGxgmAoS-I z-ytS`!)p-Sa~Iq- z8TTDd5$YaPKaukuGfP&`cpfY$@$vXStfZpg_I`j&zKv3V=b}5|odY!qsDuTczCJqaZ&OAKK&Se;0vm}$Nv`9F8PVt> z2&E`j9JBI??=!}2Dg~9RA}M6HlH6U&Fj@F)!^K7H$;&ij&bbGAL~<#Yj$DE3L>IDT zR~Ze{6twU{ndMSm5lk71%<@slWlRcrfe=g<`YcW&A)-XAd|8&~A&a?`GNUqDiA%wX zAeQU!+z;Y7T9sf<+t#aUQ#wA0%>>rI}c+*IXt!W;Tdd{wnvP zB$u|d?KD8(rSM}EgAtp0AxTi8B$6P85+09^ zOe2~WcCol%E5Ri-Lm9_wVaHxX8RCICE8tlil`=@nBF(@YQg}26=YVAlj|e2Vhe{xw z09VZ-csR0>7Ezi<1YAd!ahlo=KQDj4#ExE)q%=uF;TP;Wf|c$fx|_#wQl^p!H%!ZD zNz*JwR!4GKfa^t^QO{a}zj^0D7|}#Jn}}SV%O#A-L>wk@dL`y%kuQT>BuRD={*Yyt zNpeACL9%7RBY37%_Z=ms0Km(kG|qT3UuSNXNdNmacz`WqL2@T0^4w3sA4&3!YFjB1GzuWZy480xLS@$0d0gK1Xp71iN+U{O&WyQlmA;74*e zyU*~7V24$-4hQ~PAz7sPyu4Mn_IS{>CU*~QBp!f}Q# z*cEVdfBauv8L;Z6Az;w~;rDS_Rw{+Ne1s*3uByud@o2k!aoPU5;ZWF4rWF2Rm3+}b z(E=v`0rGC3$omL={))S^Qz{thB7U+{uC_ znfWEp-EfzsvFdX1Ov}6yXU-02&S!4=oMN+lxm3dKI&~h9f7Raym8zD`;nmWo&(N`t z6|D!g9xi&+{YB4Toql@J^VeT>(G%f!M0h4-f59`(GUfViGrphV<;CrKyuR6MMiTiYIP z*TWmL%E!0e-cO*}&30^0uctTLJKMgsZ*Di6;qBes&E4ky#xyrK_v`!HE&RTwaBG49x6{epF{oPV@~g<+l{@syEpB-5lDY_KOS#~+q=!J zeYYOn-Q90*?e*<=dp5kgv#+P4?PfH*0To80jlDKUo4d*V`g$|HncQv7``hW(p4?qe z&NkBt2sau}N1*unW<0%~OvY!(6$!?<8-t*CYpA=OfHF6?H}^0)l5cLe_RZb>WP@oQ z@ZxF$f1OR%qx(Cg9lamkY@qq|b~w4Ux1-6;{rDQ{Ozv*%bwx`$9FNcL(LDEHt-I}Z zdJnd!l3Cm#>!^738lY?BmM*? z{l!tSe0kpOeM1xgZ-su?QD^;hc>yK+aSF{ZmLFfJ_HzKW>&Nz=ZT4Aut365A)z4y( z`?&dUUT(eq%`d(J`DM*M%6ju$rl&aYU!?2vyr7@-^y5#x@ujk>`K<3BKjAO?fygu#L-VN$n?X@~oJIG|ys2R$nt@LZ{ZvFKKMbT^OkzyEXTQO9l(a`$s zTKB|O90j4)-KP3YU#rg)_1mU3>comRXbiQ^T!Wq(uk_<%_*YZ9@aG%FX!YJJCwP7J z>a063UjIgI8@*TRV084SLF>bZPFv9;@0F_e`-*Dx8eLU2-nKdeW89p)X||iq_COmc zHNSVfEiW`0+zxB99v=)G26*Sbx^ z_!H<$HJa*C`&jS3C(R?J0~2-HJl3hDB3`{YRE>JK*{JJh4W(9BM$MY87lo z{JT+0Z9-uMi<1?hK=`n&(#$T%yHCL zYK>7x(MF?x{TG^{zQX%Q1q@nOv>y1t6vnEnz4mx$v=nWqC}%LbqV%*{>(BnUrJr@6 zljEsU*C+7m`hB;5q8Lp@Y4zILXz*TZ)EZh#@6^ESlw+k+S6;u?+L{G^daCKo=82|u z+HYFmb|*@|MeD7>sd6@|fo9Of5FJ%j4DiX0{uVk_#;AX@UQq(ccT!I8O$5Zj;I4&I1(z9(2<;td4zZ4a8`<&cdh@&V?#4SbHQE1V0$ zY`jvKbLI*j2+OOkHt;T`BA~$xLWJ7^_e>(pS#=-5UFg6gl-ll`S=QWV)c3pvp#pLJ z(2G5H7~bOGT^8pa30ReS$){{VXLC090zYthl_d#ja)iUHZy6}oF0~S3@-e{?NP?Js zUUA}ZMCUVXxd1%~yv#lBF7W)=6hQ!D+hT@61PJ-Zt03R;842jjq_*vwd_g^iX>SRc z+tpVk&u5}ay30Ym1*Qtd3n{#M5y*do#&^K7$hHs&*C!r~hw3A35(vUD%MlCaykc<) z;Y*6+G7pJcEEg0e@MUs__NZ>dFb5Pv8Xb<5On4bcsYeMj5x-9zpL!njL>#aTvIAi_ z0O2r69%dV6lm(!(O)cB^9T?vAebCp2H=KoOdja#1?T8Z}r1m*?xI?I8&8Z!@3@rmq zz@!wM2Hb(n3Go7#dc>zzz$o#UMNR0$A_4sAcypV~7Bg>w-FnqE7l=d583@3kvd&)_dau* z&0O2DU68`DaiVR^FARfv+-AhW`>*P2Ds=?jrE=m{*FQE4XnU|I%)o-qEIP9m4rq&6 zx)`A|VIo0Ofb?GAY>o@|3_*Jj*~jb<;^bdiUpEWAu)IhTR-W3iNH znT*PuU*xNZ`AJypt8=-G zR-Bc2T!f_HmvNq@g=0A^O0%1#m6vfC^Y72YC}5?ySgpf^Mago$DV7z3ibw>@lFSaJ z6w5S}Wtb$Fh2_hH(L7A9?Be{K}eWeg7MX7FD6U13UoEfaSY=IJKMm=t*~ zfCE=GvB_|D~#EWk@8Qk%d#K?(0>3HWshUUlIGaU$7;EMlC# z()%7JGA@FMdQlbx(Mn!{EOQW1;@$VGN^5!ep6X5y@}73jW}+=^G$AB8-Z zJYUVhKd-{LaLTZpJD1reBH2UW%HMqdyWjuz*AF?xKK$|jzD)naUtRv~k9_^VY-ha- zT-le0TaD*gqTR!3Jl;jTc*)}OJ%dU4Jn;W{_TuG3CwNSseSCLORzVw|rc-|G1aB%{ z;Nhssb83;t`;+3+D$dgvQ`Gu7VT<=T?(Wv$>21#;7UkJ%s1$!%;h-d#s~T%}Rk5>O z_z?9|)!Hkxd}v=4`s81`d^zZcR!OLLWoOKt+QDI%@-XV6d}_vn_J>zK%F0I5l0O<~ zU+Ed?!{Z#-2TwT|JUK+>fPqN)OsDM0=+UmhM@j4U<)zD?;z7)hq^%_T#FeTSmM{3q z;iZo#aSr0YEYOpJ6|%=gQ0a6?{&sL9{!yF#Uq$=n zTE`fXu}5a!>KY6rT)UB^)7zv4w}at!py@zP*R^3?_4~WZfYC#Et?N6@*w*#F>JNv5db8>4yJ3Gn+^=@K z!ERSoTZ4;H4f^%gT5SjWwKZ7pww1L9^6TB%U^Q52`;}(t`f$DJ!|Z{!-d5FmHyCJ| zzTR&7dt*@dcg9Yu*Y(co*V=BYS4Mxg-c@^;*{=s@)_!XZcOVYv0i+Cl2Yf2M1}!yX z)gSCP+X^%tZZ_JsUK!f3zp5&&TIrg;>x0nxu-dHF+QzC3eNb(*4UE<+4OATJLv5h- z_ttPQIIGudZLRJ5b)~J>>%G2P>D3BA9IW--Mgvr|YTJj7?Yh#dVWpkvdw_bqHqLYl z;2&%ZW4G79G`qp3+U|CmwW8h{p?;a1z|8W^Frtj)f^ zT7k+dFxF~6T&;$y-2gz-xum=88WaU5*le~nD5DJqee2{Oer> zzbdluza%mG+n@gs@@9rlHjh78Pv0}c$#c_gntSins`pS@^A7RD z*zr>Wh1WXy&x!La{YTBcneX59`A-l1^ET%O>&gA@r`sLizUk0c?R$&uQFE`f{$cM6 zzD?^vds1TbxBuY}zvHd?-IJ~Q=Dq57mrviiKmW;BKRrwLE6uOBFP^&n%-koq{&Y+7 zr@LeBzW9&TF0V!TrnJwt>UP=_!afas_0;8)sy>kEsWF#NzIx2!;oOI>?y*AL388_6+N0KSL)9d;B_OGT8VGe11*u(CMQ>I0 z15lP#T|lP@H5+1A7SKo*BoRqsLlIEJX(9x4PLZg7LOtn~dh+VDbKL0j{|TU=H< z+1Di0ntG}I8$Yk&kPUmB>3(0h&$lHPypwmV{@+g3m#8AMe-4v^kCk{d`C zx*vpwa@rD(+5<%pyKS-6Q(k~{FC^J$YH!rm2kDan(($IM5;{_W3n-^HL{$|!9jPhy zCAs-VYw0R#ok~a+Uy#Pj&O}sSiSMPhiaIYp9m`Vps3r2dNImK_d##ChjD%MARp(vj zs0k_}6^4pPRT?0(FMbePEd|hR$}enQxY1D7~5*vM`aRM%-v`+=pYN;<|G)z$Q(^2~^kkwurr}+!D)j6Pp zj<`n+I^BlQYBZZV5;IW{gjTC@dVJIa8GyCW5WxRiZK2T@#Uu1ry}o`Tw2=8uR+U~~ z>PosIXA=4#%kr_To;1MOMf8@-)NX*^g2SJv@0!9u5>Jo8vw8|@NRm7dx=KTABef+S zE8x8vQiRqCsBqeVH3!eI3ST$0gYSyRfFK7!?sPj%K~+RpJtAlTejv1D;aCIvbEq*fca0g{5Kz}jyiaBK;v1BaIa>h(nKRI(s9VL9Aru4Vd;?_gj=fm(q5k%jpf-w9m9fw9hT_F*FB(qW4PCJo@bWdxWIGmHr3-w#0$_{QluFbVqI zG4KQgxK<`1ZUAtEfGn{%9fCv77ds;ZCSwd=Q$2VlP7qKtAZ|#B7x1ssG;$)K?K@+@ z+Yd3=1B46%-bn#sFeCNC(ZshvHxItU+7YKlX+ZdZFpBsO861T$FboNpnNT~7ya>ZI zE;)$gxZ?nBJ0J%gPXY?yQ`2;?2Oa^Iq1>9(1QUXS-~^!o1|}w05gZ64rV)I_Ccf=D zn8OU6E|}K~tceGv=S~GkLvuXSz&5`$eLMo+!?xwxZeWi_4zz%b$4=n*W?)RfM{JCP zz@ONT?OM%#rVVhB3C?(bxvlTD~&@ z_Q22tNCi694#lz4O5Rr?tC8NmB%ta^2vPem-MSUa|A_^4wpNRg9Sn%ae^=>arDaSNVBKm$1BO7AH9_=QPI`3+62- zEblUoOb1q!PgszgyS5du@UVDTYFmpW`y9t~5hN@tSIIOhL2*2bqLh_Ifj@f%jgrt_ zmmXtLTH+whrs&`O`wQXcfAjnKU;O;X-~V4<{`l|ezvJKVKmNu4bDsT=|JC{b{u8bK zZ_BR!`12oThel_2T0EPTGjj9NnR)P-&t}#vnnmTIFS(iJ&knaA(sA}PYzPxb- z%4_r8GCqLA&20Dw0fMhY?tu7!-&g4#v4>`Uy(sVYUU9h+r<^@@q4L4-LvtT@-EB61 znA{a~dOPRQ+;ZkWPs)Gr{6xEB{cC>aw}xFkKV!b@b`Q53`qxN}ZzO&|gx@c&o`VO= z#{arrAK-gKJ9sR_czTWGq1}Tmy+izt`YD+e=)e27zyI%*fBoNHNdNWEf7kq9{>9RH zBGV!M@k|G}4*w=3QI@0a?rgu)>ss4c^?F!sw%SJ9RdAtMb$?^6^|PIJHr%iJ+hPCA z*yuY$Um2U7zTQ^*!EU$P3^)DN+S=_6eY3IpK&|3oerr2eZ~Mdbt{&_xYuDfO2i4lz z_BShi)vtKqU(>7=56su=eSZMt_r|{7Z(+tz-wgWoUfXZ1vmsAz(Ds9k-rwxBYG>^X z0~qZ0+DhB+>)n1cu!jBJcD3IRLE37+Sq*jlY`flD)`}-0fNpDj$2sk{eM8^s1K>6U zK6PK)R=YI_xv%!aEzr|e+f5A^Xj^M|He9cVyWzgJ>g`THtG9iw$7(QGZ#MdVZ&*WX zTlK9i2w+tp!*-xs)&OR%EX@K92HQ1=t@U@nWH1~I1_ns6+pqh3-56|kXMN2Y4z=M< z1AKH{uXpQ}Zf!UEx?WYa1`_Q7X#lkXDK`3cZ|MLP4AZu7a|fmxffD2U1>K+`C&{ zR^QO^7qmYq#QrBn=${t&@|o*z61aG(^SO3I^{0n(AGeF^375Ci?hAD%z2^JM|DfO8 z9rn|8&p+DbevI7@w11?F{0Wo}843J1u-FukcG|)XK{{3ibR>3^m#>c1X8%YL;b(HU z)jn2KpB0lA6Z?daDSdhTLs8kCD{YyJD+npsUuE8lo^l4M~t%osaT~D6~(3&_`Kp9run^ zu_YfXlB&E$YD-a79wTjaMAUeR+Nylab1Gz6fS>el6j3!%L+kXq&4w&>L|GM)^hS9v z$x=g-L=~MLi>lC9fUfwqh1B;i5pt!T2*ifK^)={)-Xf%k&6e~^7TSi0rX5v#i@Ji^ z05nGBTk&JNh0N9~<*#dm%A>9nw?(L+508&VUBe{7Z9ybL+Y|34s^;UU>1hDO?^p|JozmZfh z9g_Q}3P6tz8>dXD$4H9`4hNjAr)E%641TI^n zBO{>!_ybU=rAS(%DYiAG(-B25QR4#=L4;4>lnQG0hAKL4bIjfdr)>f3MFsUkzojDO zLsMOQNPFFWS)ROU9Lq_SLSTIRGdP7H2^|S3FF^(9YRJRR33)9| zPDB|sdSGg`2WW{O<(IEe^Ho=AG;|5Q7e0gJ9n=;TaLFe390ag*8ZEFQ;9oWe9r>fu z>Na43ND@-pXsGD$N;!GiX{&ExkR-GeaVqgN3i(B|DRm=Isncpnz;U4V___lOz{2N8 z=%lB}Joy7WqoEuL!bzW}cf3Zg+h?%g5TK;+JQO7G_0noJVC}sEDZ8rJ&_T?`_$t{& z(&eKb7-OuodmZo_aO>0lk$}Ma<>MpeuU_>&0O$&!FpyQAOo8I6ht%c^^crlB?1tEW z0rXD50~*81i^mpNPX7C!|9~mQJ|(^pMjj2x*nx*IvM_w( zrTlvdo*0z6BR9Yl<1mUMYy<&4BmxA7Xm;ellS6ISw=ne_OaeDF>BMvc&#+B00tVDG zP3j*~2PW3U3oscG8W0ED*me(bb)Ud|&xcoIxJw<=4?K4~wkSEoUPBzZkx#J)7m;HT zGsMKB#F!Ar;0Xk#hdrA_B)|?#hC$S{dCZg$i_*|>h#$f8#DiBr4RoY|6HF|Scr-F> z-UTvxfo%t_5Bw)|On8X(5Nh^q!V_tuaR8EpqafgU7}VhraG!=F17qS+!<+a42o#Ja zBijZ2CYTW5j5$((F7Wkj&+#qO@p(wzaS4znW8VvD5CMI-8~Q-jcRYX01>}KU>;*3M z=@^i6ynyEm7$L`=z>g809>L?+B#I6>6#Ooj2oUpJn_!Q){^4u2M*^Va@sx@&H3*0v z28S=I&e-*QJoZVz(>mychqwWEK*qCSFd%GF>;#~!4;Hq0R)#YgQ9zRCF$5SWQw}mP z4WqyVMI7MDqsL&G5w#}18Gum@J9H_JEW5W^=$ACg)2hBXCZTl&66h*aiRPhQk0DSlp!Ce&C=ySpc-eIKWmw zO^=(-b%L>t4Ih*{ zq7isMI5D`1>Ebcw`2{N{&VyvSVxI{sNXT+L%T2{wT+A7>97c>~SplIucgAdq zy^;kiVWU~WqJ*XMNom4T9mf$}5XOQkEE$fYc^WSKNsJdXU`5K@$aWbs*s}0(ZZJkh zuDhl@ZNX!htbDHsL-u(&O<7(}JyMh)JW%^$r0aCa;%OF5QlCxjoS8YRY+QhPpVL{% z{J^)s@h5&UoBGUW3o8gb7Q53g2IC1vEJ;T*nto=4l`OybV#UimT}~-uQI%Q&sFF^K z!sqmuy$qS3&hyM=(}D}AKF6$b;$o44L4uUT7wn>3I#Ix4Kghy3POBt{6GqF#rPI*!47UNzd&i*gXv5 zDb4I4U62Hj^!+$Ek1paACoCFIXIYY#)+!w_cV7BtJdPbZ9Q!HDFv&vOH!?i!4o};5@5> za%Ne?Ng1pt7M_C-`Li+xSYZWZtc1@f;;>mzM&)_Ns-&KsmlnY+OXBHl=2;O-*~-as zjFTv=<07uIf;kaeE&x&*yU{dAlX6*>^N>x!b&AjfW3jAQ5T7I<>-n;r#)LW9GA}X! zg)Qdc%3xChPM9)mM@E#pxqDvNa~iWSw3pK)T7C)2iy&E$h%sEuS57%)VVqg8s^+sY zD9-Z)J{pRd7v=DFZISRi^NBT`PZw4+h0kT4@tJMlh)ZT)gO&DmKry_HX967_u`H$!0-9HMy$4-9Zh8of-Ud+PD{hnf zBkj8{q8pj-w`uwH_M_(B#OrUR8s8ssAbG>~dh|^!o7^7`gN^Y1{ODS{Z1&6A9lG8u zzXw`)F9v->*nL{ZC$l;3r#f&QgPSCP{LY=b1aJDk#;c3jIJgq?Mm*2Gaf;bZUIb_M z0M+XjTuIL%OK!|}6Am9=%Q=M`2MYxD9WkzL{V=VdyxaLGyJX54lDk8J;FXd$(f-?9 z2=i;YKzSr=rrgh4aPxbj9FjL4tcKa6C3CNpUxz$$FnYCM9{?0w-@E(j zVf&iT;yiWptA8iAq~k}~0{>?CI9uSq_~C4Uki=o~Hz7^p2-Q1%Rqd_eS!L}ieXkF! zm7#4{!_9i5_3O31-|(Ucyx2gc?P^Wi>iV!+4F;C3t*q^EukZJpy{_+h(AhGEwN|gI z{XiRP#&ED7taKjU-e_9I!{XLfAL!eGK3r>?YBSI_o1s?q*F18*(scN5R~ctD-0SOS z>-A={-JR82UYDS%*6YJQet{i+WGfLT4L*4v%d2YCjTW*LT7 zRn>NHXzTT0IMDP>f4wmVwPw|z=*p-E7R=Ch+71L;0B=B$zg3`nWmxdHxB4J~zFTYk z{&2I~YMb3|x8AP$yLz)8^Z|x?u;P^>HkcxIhGFU>V7-&q$=(>PR6xZTwLTmbnhTKUscoj)AY{AHom8(J6NC>8LXRD!Gc z^iNN)e^g@O-tF(iW}n;k{;g?`?|pA;`xE!>){gjI1&N2#fBM}|m*1QA1es@E{E~^k zto?NOcUgTcMR1jt@^o^_l?&WSX}F{GPrpR^rwT6I7wO46ce{SfyMKDZ^L}Z&FUXIP zxV*eO?U^~xV^n=_z%8RkJ%g7pLhn>EWVNY^5^8!4)RDHYlw+ya>2?%^ zgxM=}7%xg1Qh1b9Jr+b+Y4ms?wJnQ{rYMRCHB>=3K}a4*62F0(FO_CT(+}a+c3VP< zB#4ax-@N}umU$Tgq%;M!ry#zq95tmAL6&+#Q;-@eYKnZfx1^$%qRdklUIP_H>WD(~ ztSvPp5h%;zdo`_;1A2k)V+YkU2L6*h#XI>=$U6mj> zWIVhSr6yL;5xPR-RZ{~25vV2~HPqK&CgqiI^j1PIk=~Md5etMS5;Ene;UT>%e5_xM zbS(X?HB^p||6+_(B)xrqe1hH}5#Z!S7sNpZo`E!Qi2!w)J){VV&=AzlI}iXYEPxM5 zTy0(*pvTKroPgbqR7sJVP1JrRfTDm^zpfm9jP0ofWI z@8k$c^4oK%c_>_<9s}FgO0$dJ!L+6($r|t+^AwI&L+Bk14b%~vVgq%XFHsA;QaVCP zqm6n%@=~mN4G~rl*d2+y^aN^hFP(_5yGVnDBR4fL8aS6IYu%=#io7-ntQervm1OV- zLE$9Fk}7~3NKFM~;&KUsro2XCqs7Z9fYsaG#=#_~0pHHFT>`^Q;_&$JI1J&n9a4`(#In2)kD%A4yq6Oo-Kw4m9RV|Y9~?)%ilCUz}*WE<9KWVnHE zPbPsw3^RbQ*1m5}oCy#4jx8MU?ew!)np8>|OOcxs@2zb_sMSZ?0pEy3@ zVgG=FQOKA_ze8Tw0Rv)|H{nWQFd}gRp6NjNu7Be4q78g2Kc4t5^+U%afde>FY+=^{ z1U)yzlMqvmq2oEWYZw#DHa!On?3%u7+NR@!6-dAf9$?3|UDpl*$2Jd=I%5~+;=l+1 zQ5;OT3_hh6nA#jU6KsQl9n%|o{>bxOH}Gs;rouGskvB2TiR*ceIkFvN;`v~7+vDXK zJR2Yixch*A`kphH7$66Dmp^tKa7Qra*mihA40U~8bYP4FJTWHVRjvhEg5z@-D9>b= z1lY&K4<=;nfkp7hH+>ucRc~x!pNs%fKpl{`JTSfiN;tN`GbP*+&vW2q6=2yAc=7;) zF|Xob7<`fkON{d56px#Tjy(q!86b7Y0RaPzZE`Trh!Y{c0}ew1N+u>RTEQzg_{PYz zK~u-YE-xj*b5dXcxHZ@%4Eza(|HhN?$n{5tXIhSD!Xf~p1g>ud&IG6e@E|TZlsWNj zXY7r^P#!lAEER6R$tVEOfq~@&;5p!MyxI!bKX7@9QfL5JzQvQ4D7b~mD^FPPGy$Ii zn|h{g9g0=hJSigeneEP*7n_T7gJDYNZl2^*mRiwyJU!1cD=dE-FN%!$)X!47W-NEY zx*X*Tf{SE6Us`E;o+oU!aM|p0K4TX}fs;|1u&4}j8ZTIxhty$|6~U6sL)S^pooP}q zHpeU_;n^yPLm$*z) zmR3dXd``o0VJH3tVRo4PlX(%9X+?5tIU|v`Ok#MSTP83yyDZ{hvC8WiW+1X{W(g~! zWiod2GAKjJLQp*o=d%>EWXfLEQdRavo=u|>wFAxonNSu@+=>-c`_M?vsGHNs3;?+a?Dv?lwaJ; zOC|t3VO1JMb`bkyG6MsRS%FzFO`MDsv7fTih;at*I$0P6fM;5ebeZG{ohEd`SQy5k zG0SRJ<%LUtAzhx2Q+B>8TxvyTv?{`cEf;A*NaQc0s7w-ngtLhGqn!LU_!3U@Aj{!{ zsc=`bICs;jG5O4vpp`?<0Z5k38HPcNFL}kjRP>SWt!NNEVXNiRkntQY97gn;2C&q=Wnoiy6Y#H0>Y!UsI%@<^qL=M3-#_Gh4 z;9Y7NX6I!zyDqQ3#y|g0FNnEfKEWpG`iwv_8R$!Lb3@=z7o(E|F>n}OK zfMvumEGTvX-y>=-f;Y;~zqQLRb0hy!CbO($VKT?C!dT3TB1vY;^K8aw#z;EP>`7M6 zqc~@tS4Wt+KqyYLl4n0Ag=?XSL-K5-}hkFP?k{^PLx({b0k z?Q7`y(a!v5ww#C8DHspKw6pRmd_0}yoU1jv7yLJ8v%-gIcM>Pur?UtiHtSK(SF**u z*ZG0{SHXg-(DO||+qeyFM+c$rWpvz%^tD~nxyImbroy*(;$OEbByJKEIJ5E=wDca2 zoAz8;h?`a%&^|zTfNp$`+;vOtT$hil7Zisq7;g0Yw;tm0Rk+8QF4KGb?ozq+$njS} z?s!$`9f;j(c|UpLn|UkVO_Bpw{K_2HM!Cs;cq;uQ641?yKDCB5H2zB0=_3;xhzx@yi>tkNs{+$0X= zH%uNSTAV(SXz}|WPqd&(k^M~=W+X=2t+lW8y5h$w7+akm6EPT88*5+Jx>f7jowh&I zca^d2Z_du@wYIZ1yJ5Z4;gTO#Q0?~mpubvg_uFc_>F>_!VKwY;_qsLMXlFxxUk%sw zzS{H$wYIjl#!6oew4pv6Xx47MHDH=%RJ_Q-b~CUn7|>twf)D%6S-l_Z_WOD;)VDBrYwXt5 zsv7L|l|ImUl?Gne;cQ)No9%E{YgIkiYxUr&PQzxXX?qx1X#=C$_1D^PsDmPd{d&&} zHLMLlsoq;vz1wexL&K;CJ6&II27uyjTN~D}vhXbzu*ROJR{+;~Rqxke z6;PPhYFG{T^~M@%yi$f$4>#6!yV-C0+j^&2>m65g-(Oq1!D=^L5BRYknzqvF9UykL z1HtwK{i;^O8s_PhVeB`$Wt?%?>phrwwcBZ11N8s(42oadukF|N=WI`%L~#{=eRT0; z^A90b=YD+lD(ZS2z&5{E_y1l1+YSA@0a^2#=U+V0exyo(>Hoqy4|eE1d8oj>W<7KF z3cu?R_`{@tt4YsKyVqc{`H;Y!VO&J}E7qLk4Hl155$;qyxFukR_m1k|?QsE!gSA8F zX_FrKIA4c7qVc#rJ}cu-%fqnlJRaD);e(!U&wNUtC)%TIf(LvbXB#{g;KnF7h(5H= zFZIqJZI8U{KA&eYlkR|eZ`3VP&zFEO`J9{cDDKBXza1OC3e8^L&t<6YPON@GMgo8F z)BTewzI6)5lk$A8RlmFV(P|NQr1(~d{r1jx1Mm;UtA6(&^8aAk!>&gsXFNFF;YQAj zyZ4^Tb$NWE#MhjTJ1l;>ck^q{0~uI5(PDHQw%w<-_$c5>7~ zt$5U<4;A7>6f>0Ou4A9Y0k4OKH(EBdxe>5cl3GG4S zNaNA#SD!jankd?_{GNxFMWmp{0HhSuE>ap2QrbfEL%Yp4;kVIgqc1hoW(&3X0T1H) zZd*ntZAH>$q4!#CC~$*Enj0rvAhDsUNNOKaG?X^z(QXKGN9-xGBA&F-8>!tqZJ~+k zohss|e&ge(H!u|j%k5V@%bI;Aib&n*}`8yT0n(g+92s%g~ zcv=Pu0n8KWaA*S(%q}{Td+pc4JJgbemce)Sw}Cb&)Nj8LP)8QUtMe-q3AB0jA3mX8 z*=RynyWQeB9jYuX8j93XPg>}u+>zzho7Y04jntQN|Fwut#8yWfzY+zd(LU5!_#^{% zYUAX@N9Z^b(Z_a2Z=;SPH^B_jK)IC9yQ|m#bfWR%5J&*)NRo!Sr(#oRx73%a{IWMf z%@=>Ez8*9IIV5-9@I087EXt}X$dV|4)fBGUTS-!QVgNdlB>7{j_u*Y%kx%6lK}E_d zso&}Jo9{v1m!RR{Xp*kjMF&+Sp(!dNYP^toB0A~}c(z4DdCN0RTE_s}ksxt=C4LkI z0CglPD$<%7c%Sg;p9rdSrYfj;eAE{5!ONqQwtzU;iX`^XdvFwK44{Y&Q8{iRq-$N& zeQ{uh8eK(FT5X{#$K(}=qPAtBdGev#?;M}6TXL%-tDsr-rlB?D478)&4Zpl4C7JGK{ZO<4c z;LhehhsA`N7s%_O-ceH&ssG-ZU z@=j<#_px-^c*g;1_XJ+?MSLN2-~MZ%`*P54gA2bFyN%^X^hWHyXsUoh4;)!hd(N>e zb<|^36gp^v6nwv4X?Ce4iXn zY`8i_fuFPx_`Gfb3=4c7q9&f}^O^`YPi-*$vEv)#kr(*p#P*!P<~11(=N3@DkKYdh zm-vBenZ^j_Q#WuaCZ0na*Cg1TjBUqv#$EtCh!@x)Fmw$b$qoa5%qtyu9xvw*hSag( z4_nx?{lFTzyl8=gF^%{)H}6o6AS7OBlZl5h89TN+vOJTxfrWX&fe8;c2jc+qP4i&@ z-=TT+|0s$~evSjC{45H~q5-xKg&G3O4lrm>Tz_H^7u2>~Y+}lj6ZnpQpyd!A=LT>< zJlA$DLamWUNMQ35HXI&r_UyoREN|kBY}+yd&mtB-ufhUMY`E>%{6q;CG~%asxV{Cz z^4ta6;MFpGpI43mxDEvnOzaw_>$?Wwr)&@h`(`j2Ii`(W&!u1;9@_VPY#%6(fCn)N zaIhTD9oZHc*^`i;EinPhTc+#zrb|aa78u(mKb^ugMh2!nFvDQ&iRU;Y%NT=s#va8J zc;shnI3CCsj9kYZ8Ka2}l31o^@+5{a^)UZd%&Sp=^-V9Jpp3y!gW%|b0r}A<)bbqL zw{6gv*Uum$?15#ljrk!MyefnXhIcJ~k_G`U#HQ==LLY=zU*IJ|_>msG!~s8lgHX>h zyb%tZ;80~E;72|1Iv)I}20t7*6P~Z)c{CW)Z~_{J*a{;zif|b4V<#-^PlC`t%px!` zg3gGi`gq`0@T=aZAvp5b899bwfZEvPM?sht-~%oMIt3wiUX70Md0#L#FH-o?y+SPa7JQ-&x1<`uns8kELg()SF#my{{f(!G0*0S;Kxva zBNHxoW)G00qY!}MSyEhc3S>dL!=406!x2~FAS?wrcuf*&@!vt<=n=eQgp}9C@cEu_ z&kZL$@g>BE6Doc~RtXMWaQy^lp`WMA^I(>P%U_lyDP}&N(OF)QMKsIuY8n^wFIlm4 z7Wp*vlEo|wvW&U&Sx9D+fFx`hFjj=1S3=1$VkxdxVZuV^JS^?s(yCxME>?gF%P;NH z0toV1ntt|D`*Unu*vT}BXJK4K`7|-hddag8(kuw47LEOA6|bp(i8GoNmbZ+j@fc@O zju(9Idz7=Ar=CLG5%g^a@S}g)rEy@LpvKdbE+-H?bW_TL1D0PWp7fwcs$_p^d zd^2I$bjivn$Q-{YoWv%vS>hyK`N1@0NnZGu#4&RxHQ2>GnMPykup*mf%Xo24=E1mf#4M`j^QhiGg8Qd%ho2?>u&cfF)njI>BDK zJhyq#6q-jdugVf6fm;+gUEny2&jUZ5E~oC2xh{+SG-TkBv^>ww!Rm~a#rQG^Cq-D~ zd0;p}SrBYzUd*P3m9lvpxz=ofxrW6k4p(4k16CsooFZg)0L#vvm0`(@fMOSpMf-9xd`12T5MC zW$rRIW4I_-oE9n03q~WDh$}#Q?$;5WF2IZ8i07{m;E$K*(L81>C`y*ao|m&YDOgJK zxcEYHm)CNLNMa`QsXvWLic>QMHkA3^Dx2nudBjR5bLXF{c^b3a0-z{crU`=&%UM7S z7EhOfon~x#j!C#IO3D($o~3~k1wr9NX_!vWSNXJHMVg0`xwG=4gsslmbUI-S)QO@j zViyqr5?@4%*=l)FR1syC9kGAHlj&xxD!$C=oXld9=d1v&<{^t2O-n#AO?^Ky9eB&N zrimYuWy*NXha6UpRTw5NmkG#AKj+2t3rllzk))OHdRaJi*lZSLc^#K!=<#Yy_4%rV z+3bsh8BZok+3Y;5KhLAuO#!|cd^Xgqv|)T&oS%mg;Fy&~FhFv_X&o7Te2#SrtC6c z=zx?T284}Y6=@0o;*cIQVMSLe{%44&|b*z*}k#ERdhpzqW zaO!nZz=OjgZd!cv$R{LM&z5l$za@90?7`vWghLzOjpZMB-XufZ%}98pNPNrui7Enj zBl>o5GuOLfamdP`SDn{d#y4^O2VwEa*T?KhnI5)>5&nEuUMcwK{DZ5J(d;UlWaeGt z@SwKCQ^t#LMfC1Gx!2?4H1_VP@l@8qm07N2gOB0oSk12M7Nqf4Oz%{T$nR7TdGgE) z^R|~yo;~YR)#O{IA$a%Wk`#RYy_B2ifywTBxPK*9^i}jHj@C%7 zgdW{b7)c(D`s=}du`RPcG_^D4TjoQAFir;GpM)Lq2$E2hG}Qp!Dg?WX~Xq)Q0=vyHqckY zYB=0idt`)mGKl&S12@-JSKX%1f-*D?>l4Ho(l#s@hs@ zf!=DrHmdD@U2E$djE5O3&Dw0W!A2Wa)ruFEsOn1J^!0i-Tn%@|POE`AjNc7+gZ^$+ z?e~>2tgQWTr|s9;@T_0$d5(r=t*n(^t!k~(&idMBxYhb~ZS;q$fmW?Fej*1i8!_Mm zcl)Z|@A%;w`cUg{HDfTWL0)}h3|G7LX1iVKt7@&){74L~zpJ#>(6}xXQS}G={n>sE z{~2fc*>0s(*4b{a4+lf5?(f!>v8(#kdSBP;jcx$SeS;s%p&Najli#i^eY*l)Lw&X0 ztk(4at}P2--08dRu3v+xwgx|EW1#(~32Oe@er>`(t{U#WY39=dzS+JR9Y0X|!SVoCWiGxk;OTqzKdMf{p*>d#<35)^f#|(7m*>6b zu3}dL+>ejn#>Ou12FWg;3Rpk8)Bl-3^utKq<-^OTgTwb;-n@P){(kx0K>6h(F@9)| z_@Ct{gWL8bJeN!jEAt;L=vWrcCF!K8B=6)#>pkkpN~0~*qn4;3-0BHu z;^eK+>Gqq=o}j$wE5b+AL!H(~;ZsXEe%F#4$&oBJB>70}bzUf=7e|8J>>dq{M9J!* zqN}OL5^|b@3rRqIQ8-Z=VqZ|KVgG3GLYLq4NJ^*EkrnL-HASVboGQ|>s-i|)`t%O9|LJkNFMpIiNWu&Mbw_He@10gl{UAvV zMGvJ`yQiQd$q?G;xD<{xGB=ou|c3+9z=IQCA^-_G*7v+ZB1gcX2z-|jsTTsMi@6As_M`_FA zCw?A4qbW9}Hu%a1v8k$Zt1W$QDK9!ml9iWgLsC%l4cJzYnkqO#zx}>(+>r)d(P}o7 zBjs2Sg;uX2A0tT<8}E*L+AFzlc2t>%!u9`IY<1qeYzVDJbIA`b5MO_IE9x%>N3G)H zY0Ew{J_$%_wIl=<;pZ1fC(;Ylea|ENVs|FVuZ5O)B+E!{qa#&qOKL|^L`gzTMV15} zlt!(SMoa0-p9D~{C5UhX#Of+qUl5vIBsWCy-J26pl0{h&lle`S$HAHeeq2{Q9&Y!va5?=-?u7)88zKlONACLD#t ziCi=AF^^2aO&s|yiKrh^hsVSsFXR=edC`75A})>szIoTTXhiu5=@T5#iBCr)3~=Cw zWb9e|9Qi235iepN@Bpd}Jo$Ft35AdNfS)@LOke~IcP4~HrWN{5Wcv}11X+X^jgKr4 zlE-{#VDi|W%}=?H0_?f2L3zF(aCe>P5F+JT(16G2BFn&@KRWEq9tA<@g1WryJmLH? z_JeWAh_rOUBoo-T|cz=Hg@7#;RyR9!gn)=*5SwmmmDg} zd%P4sKd_#o8o>=7fSdSypSv5tR~)cb6cE6VfEiur4MX1_1>T5Tjqi--`h}B#gkXyZ z?qM<}*sueKMvm+8ZT7Am@lDW?Wko*ar`}`V3+UJBOBDPLo%Wx91tG1 z33;7=eyjq=-s4%O5kEqJ;;*NLxe>vp2S5|gHF%MHGI6L$c=*)tscmu#l1XS|>Ki_< zqCh4S9-BSH*B#1_1pw=LyhOhnM3d0PpaQs=Kju5LaY(2KL&4{{cHGOkyHcj#hrYeo(Qr}r&T z22kaTk9!k8X<@>HnBYbwWxgLJU$U4aj_;*xTAH(xEiJQP%%5dhna^kWmm8h*(?F?pTvX(pyMK-!92jsF8pW~(cJw!Ci#?v7mI~Gu3Q#}tVl~j5{joZ zOFXuSDNEy7bY5bX7Iwl5qX%^ye_2FR#*bTw7>g2rJe}DIkDfa5e0E7#%wTR&vNgpl zF8S%`c;;5C%!h$W{#A zJy_1BzbSGyiK7YgnIBVgZ7*|{_{@$&*L2yJcoIa6+H5)kKaQ6cd}y$#2Lx#`b>q+0 zA}A{6m25s+WHXns&m}7?I(9!7gjCkjTKHj7GOsWJMJI3zmPX4IDlWJ$Bjck)e0e|YU5;2+SAFG*39M5%PU2k6Dz=)Ni{ zGvbRcz6eTG9-MP_>F;o|;FwALU8$mbFl`Uh+|^~r)qP~s9^cFP@4w^^P%0MSSk1IU zC@sogV(IR1q|_`X55WN)3iJTN3U(P58H^sMkRNn+4$?JQ*`3`@?Y`@S5`{LiSQ^;)fddSR=(&#r{5T*gQ0e|<7)>`+#-(Ai=&HTjP5a){y}iC#^kywxzg^t+mTc^Nv*@;Zi_U7Z>Mgnpt<`IH+Uw;8 zSi?PSrmvP@Gu~TnI=yat$)?(RxVJZ2>vq+dgU$RJB+0>!e7Wg$^i~@*%2!vn`to+Z zV4YUW)#|Bx`_=Ncd)4VJSG}Ec`)#Yc>dso7rCyk}Uv<{2?ws|WuhyDg7`AJj78?X^ z?OJy=>*zY0Vcliddb8El8noTpt)sUo8Cra8`SDR32s}xwbott7W!>>wl`w`$%p-?_EY)`|zkY~)y#j(e7+^kq^*kr?7|8aB0&4Cg!e5EK9&3M)-TSdPk2Y?<_xIf5V|nct z`4aB=n(24&*ioqI@pljTaz|)svv1mLzZPux!|FOpqwVVs7K1-ZswdnzFTLfYj`|V2g(Y1rRZ5(CCUd7JAZqNZjk+!=wetCQ z(i`*NR4xVK=a-#o>EvUnA@Ooq;rV7=Qd^(vve>9fT~QW9T^3I2YF$(Wu_OWOv1OE- zVgvlBUVYF()b4p-+ZLPt?~ z&>1cZBL9O_63Rn`E2%Q43yT#kW`<=1xa8*miVc{3l^`aCt^wV)l;5(!*eGB z*On_awfD0MR}xh5qriGsRkg~(h;^P*ae*A}jC<`C>3$D#g z*!fWZlQ^vRYodCtRo=8}JYN?iwsn6lNvc#X)l21bPLzL9Dv9qTx%Sp8UGN_yq0PN* zUbeWJq&AwJQ}LwUIqgWw2|tvjQdg22-1};Sd-qnUlxnKP*RC&4fMUxDbw_D7nqrl0 zVzVT6Wg#h7PvuONM5!vMT-2;pxiXx?@+HsCz1pfu_4?b=yGm0QWl^aJXIZ`8Rz>BD z%)fb4s?~X+ER^2LC9!jHaXQwgXMe$QrslAuW94oJIVVrTYB)_Rv#17X` zTIb;4-QnfaI@pj4ZAB@SFU!K;{`M~o+wh2Gxd>^6O|9Yj=-MS<=!>!ETHe5QiP3im zCfC^Q16qMBK%;>61z-pE2H0@>mgd55Xz=<3BkXH7lvrSQT^KZDPuCoc^nsHI2nO;o zASCA2S9suhmhWmHO^ZP3mwRS{Ok9^uXb%n6b?EB0M|=~Ew+V38kgaXIvwp-Wm{uO71uQz; z_kf`XR@Cm0AUv=wf_-e;tRD#RvX3OhFtIrV7|>-ykjcUW{m%CtfPGxu1mq6PfWeH~ zB#r}i+{AMrj05l^fgV6n(=Erl?z1^;$M!VO2eD{YAr{kgunn9&jD3T}bghA9*tW~= zx{lj-9UGjDF`IeV2S;Oo`G89Xj8b;T#TF?Xj&1YWg&+c<9hY_ov< zOfb=QaAD+w!2jH~bs#GO?&;w^^0x{?#qPrXdhV9G$c`akne3yz2{0o&R}LQP8nz0@ zZ*~-sTbQ5wCSoi0d>gyArn5_M=ry3EnzqMkNqpp3VDfDD*<}~dG0$?0;#gb6*4ZI( z`w+q;y3SVNJ3btu?e-$ybUmcwR^|$EU;| z`w>d@T&Et5LyLk@?v&;}^+P{OqBI|F#O2TtSDv) zfU$3sY6%&Ik$>ZUrY=olnk2rLc%dfv!6fI%mP4|K5;x_6sH~?&>JgY$I}~6 zqjYAocV|lTB=#H#9)?-$M%bd*a=nb^gigJ{2vhcR&h{}LM}ZgnPD&=gmnAPKN*g^7Vav!88rLQzO5PCP_&TZ=|XLpXxS;jZOR-|ame$pk$*!+}x<20VyF^x!sNHQ8lGa3bG zLNnyCZ5jDw;-Q$Ppv)Zg?a)bFYM4KSzB3uIpS1L|>m{ib8zZ)ZPNI)+62!r9I3uV( zo6Wr8`0EeBXnf;knIE|}VznRVv44{~G$wYK+`(V%zy9s-e)->j{UZEz2gYn4(-&xs zdw`hWJu}A4M_UvC)EzF$XD#+7HmQH?zx0rj}H2W`A*`s*cKc; zAww1PKbGC@uvq)`?8e+H7Dojt+fF=d$HfW(Qmvk^vTYtxYyR&z0K`hUw}*T`nJ8$R^U-w5XIK5*1Xm2 zZJA=d`DU}}-fpzssy$z|=F9eN8{BvoTcX%{-f4G%DAt>Idj(Uhw`q5@-j*rWozJza zb$bpLzum4r@2$Ga^}4lO&gZvUw*xN3o%VdaTCQ4)<$5*K;pV)x=*(8@S$or+cWzsq zPG`9;NMfzq_G;Ccw+oKgywm9w95I$M%Y{wSY3rNKRd=>o-1e@z;J3?Stl0|J;56L2 z0^AKaVwwiTH8%C43(B{*o!j+d*IFzzP{n2~ww7+IwQ6bejt083EYaoic5}xQ+ss=m zaHrRv-Lu42o8@|=UA0#aIbz)ft9Wa+-01U#-r2NPtZ%^)Yu~Owz8FYi^V?eue1jLa z-34&)*1ZKxI`6X8=rdNK9@M|Z3iFe!?N9Be_NQwvGQ%D{_V*qF7)R6~AGYVDERUfE z_mlilB%dSb!t-{#-ctzZRp`W%h~{C^KMJaOI^aDa+~(1br^Q*CKu25cJ%o@XBB>w`ZgL>c#u7faJbqyL@EO{`?eR z7yK#GQr`+SiQ`lGEmxLnB|#|5hQ#-3V;KlaT!jTGS7(;uZb0@EY`S6`(wGTiekB>mMf*VH4)O|0SBs7LGHAADqKh> zgX&qi%Bz=xB1%=3!MW0HvOo0XE+>_F@#I7~l@vwcFYD5U%F-!GYMCp4lx3Auq*_`0 zdw|PS;J@)xfxmbsvrbB>3CgUM%PKEaO5HLrt(1mRyW|DXo-CI|rNlBhWh<|JC^zLx zuBr;al;Ueupoud>q1ZMmwj5k26QHN+21L8@GuLZefaI8m)tIe|s6 zglkUaY)L$=u=U8*R>MwOS& zROP#}a0)uCZ+NApyyvSGwp>!Hmt<4gjhy051d3*;gr8SFO}3%^-`<}9N$!BNtSqC zRywBw$d_KQ5OSTJ;Zaj%g<_#qiA^br-|6wT;|IHFa1KPvO`qsvJH{A z63^Ae^EYR2L{dXb?GF>S|jkmvP%jFFF7 zM7t0mg~W&kcoZNN2>XBzAs=Z7#2gEkS7ai`8^FWeYvlEHwpjS`JT$Ui&qBcN-^Zg-k$hH^_dvT3fA3(zZxN!y+@xV&eW0`6m zMt!Gm0euSqHXA%)i8}<~&{J+*&h~Nuy0c(5YZ``)*y&(f zNq}$YgFvX|xWJ_&rf2Jpjj#@Y96Jj`1odPQjs6f>7S^o-<|6i#j8ZmY>AIR{Ba={v z1aU&r2nFLP4OtHw`%_?Av4DO?aFpbJkl=_0BN9@ZX47aC<>u_hN?Gk`Hn1WMj3EKt z@bmsCblGkMKAl)}mIY~?dO@0KwwvVXIHL5cN2x(ZLz9NlFdb*}@pNKjgpMgr3H8H~ zL&g)^nT%Oh;{Z{gf@CAks69alR4{K6FSNqYup;p6wb(l#!)|KFPKvUe#9!i3HUTbI zW~M2obUGTP(-Cok&>m30*P^d9juR9`zGahmZ0pnvyznNC!yugxP?ltwIr7sn!ISC4 z@#8W3KEOD45}HTYr_mSy9%n={HcuRc(ZBi>AxuO4#>08;j(s`<9_9!GWRiaJhcRe~ zWjAxf+P&+$Ou0rDGpdkb>!b=X6Aq@ig{E#^h%+k6!i0S68M#bYtUt&$*e7#?!f#v11a9 z360$#$7Y7nC>#XrXI_|knjR1rEfxmbr;r2|9g&>vwl|#68yaOa39Zp6p3v!d<|iR5 zn;V#)NjgrPnd>`&1)?*^G^yVYoH01F`ahT?&_N57Cb>lk^vJfkEbV>^wlnB)_ij)Ek)3UiWB)c91rhe*~BRhygmWN^GVMr&G zdg-U|tLsmV+;D0B$r_AloF{ZLWk1d79^?AQzxnO&ewqLED=A*^9N*1zw0l&4=c5-L zs^*!8fYBCh2p{4=2l&la)bPQR|DBqoli%ZHIDg3x5^a0kP0BJsdt%c)IDrpXGY|Ml zcpE#&?c4=KEG=+4JJ0naQ^GBDzz}na{O!Hb<2~R)_SqB@?>S5dj)U<5>K7l5x+_<< z2Rz7redLJNQ)x`&{g!j$ZbB%VGSD5bw5BH1OZqti)lKH;oN3|Ju z?IG^7@A(YtY;=!)dPSO#F-BNox{qSAfCoL;uZw86t#An3y8+K8p6y;2>kRI}wtc@M znW9?yQxnhq8t#tFQH;xhj<^5=W0>rLI^z?7>pvd>xPJF~fGZ5+@Hbu*gbB9-Ue|oq zop-cVr*+%z_HKcxbfp)>uB+a2`YEj()3O^}1KH*=ExYYiXSLR~ z4I2u)Cf2W|_qL=iy}jOa=B-UvU#@`EwbtgW)A|;A>6vp|bUv>3O zZ_~QcXKj}Aj?T4M&JO5YKw4X^JKZgxYq9CAmMeYLnuB9wyF1sq>nm_opL% zZvHe+^nYqUwSTtl5uA1KEPfC0JcT*-^dRfiT|zv$o7c9sN=*)pt+ipW+DjM3z_6kd9d0 z{W!qmS3lo_CC}Y{e(-}%ht_=G7UR1c`1K|0!I#7AR2m9haJX)v5Wht$?lI4~%l@tRvVW z&s8f8jz4dx=cn9ht<*VFO27VE{>K{kUggT2%M)3w%A$Q)`*&>2N2Me3JTJiG|6YYt z%F5Nb&=AdvbivpDt}8ccoFG(1`BdQ5Q(mvun$3o!m838A?_^0Sb0tycMNS%kZ<$h2 z`Hs)?TuUv9k|HWKQB*3G)3?8v2_>~r`wt>tI~RCS20c2iekzGIj{i>KL{%yr!m1|? zseH!slGGH>1U7Bwy`->vRe=*FvC0e5FVxmMrTl?!%bcW^8bZA!^=l^}glD~%>Q~b6 z8vfXl8YNL|v{g=OSH(8>uN&px|1VXp^Vgj6h6VZ{o}H+GV+cUBQdwZJu9N|zcvoTx zbuPPHRV-D@mn@Fpm3diEq(3_qJLQ_%l>ayPcU&m6-ta9pk5Fq0pjxPu+arlHmAcA0 zUtY1vzSM6`5Q97vZ!bi=`IpH{mV^O;Mb2Qb~|1oS?GOHQ3Ix{|6ZWW9q0^ z<6*&)a9ZN(l6Wch_)?XfIGJr|<>HjD32(W!#9e;4XeuY?*K()V65f@{XKzJZY5q(( zQ>yJ&xy?zkBJv75kZM&_>$3E3PgJQ=5!EI;A!1*soL`n|%EgKLhOcwNnJB4kPVJvb z})9KB7Y(AaMIaoYI05C&-fBA)T$+^{I~3bre^2^-F1nN zfp6mwg6#tAz`ACb9@uWND*&RfYs5B?#kzuFnr}LTp+j`Qf{+12HB@}0F<2z4Pdv>l zC^Ihh*&W+6!Hdh%0K5X3K;rriz*dFfmt(pZxhyueF!E5L?=~dY*s_PHj~oYltNI8b zyH8veLiey~BGWR6eQjftARS`|J}DG}ghK@4V;-=3FnfUg)aBUzf zp}uWjW0R%9CUmfM&0erkY`u6ewDqCOh7U0df{5;bl{V{QIIe@8Yh)PgLom>RNPz(j z23Ti#6T`J_G_bCRz|YbOt1gx&(pY@Q2JJk8UE4ywr(*+*+lXspuaMiruA_rip5u^f z7iI+<#@4QZh~x|$8x042(_o#PYit)Db&l)Vngv#Ax(l2w@X13Mv8s3j$6{STsL}T| z1S~Lu*sg;6pJM{dXb-Nj;bImY7HL!%=QA((722`!Wwaf;T4RAH$nS-KI;OjR8DL~CK!Mx4EpcCkWdLs4;aLm9Kt1__B0JQV4 zZ+gZM3IgjO8Zf=s1{VT|*hjG8KI&r@0~lJCVY0ooHDIH8a2^qWgqGub1SBOLRx{fK zq*2pMP$&dAih%i=ZFs|h1zvcz540~7bU+OiZO3@drXKri-Bf9VcgngWjsfhz{O~c8+ z#ZEk+Ry+t|i$-P+lqZ^Ic04g6&!#j)7M)BdK}6a6ETjEVmboD!&9?e5{oKL0!{gj#}Xy~EOS%l|FkVJ8W{KyUr5Y~%l*_0Zyn1UK;h>QUF)W&h@ zhcu^Im|)Xo3vj;}u0a!j7`vb7Byb#OmbihRhk@-vvQ-{@A_fp?MNkU?_E=oskZiZnDKui)?()BFCmTh8~RkG|RrwAZOL}#=+c+iOJqa(_oP%L6|P0 zkdA{<60(db8nNiE=f#+Mt`~a&oduKr^pln4BX%auAg5@+cEI&XsAJ0t7O@@NgsgHn zA*o9fl!R{JkQfeKl=cU%9#3fyM^PN4Iqf?n1b8M%a#qmPiGpxCB_oQ*i+mnX<{ZaC(BF^WrDEC;wl z_->-74Q^$|{$+5#h~51=SVr3~yI2L@Ax0Y7MGo&qMF(py{)MvN@wcM<;obd>A`F2r zM?tD!pOS5D5wt@_*j*JMhaD`m`zJB)f*_OYXhmND(?UQABzYC000000RIL6LPG)oMPux}ON=v1mL8UG zCf`g}R#jI0Pm)P8-v0nfG-yT41Xzuyz z=OZ%W#5pH|WPInGi2UzPDe4#3H2TG=OHmy4ud;V#6wn{Wq34A^LYWsL@)UR|aZ!kn z>&FpX@RJ}*sB)t$i*2u`D!uKc+}{++vbWh@cFUEvl?qweNWG0Dm6Ehp1U)B^wDXexRVg--Divyfvr>WScBOW=t5RBRdP})jgLIc``LZj^ z@@iYin{FX(6|J}IZ^~6su9mXgTlQq7P>D|4LhTj(?Hc6YuAu*Qv0W{-rKFYHB~&S- zqAT|#r6+gGvgpf2AuWr`ZK+A}rM#578+EfS%55q23aBK3uBzOFZb0EeUac;-YOz^D zRaMz&P`l`sAoxn%fbbF+WUFmJt^QhD79cn1Ew8&9ZB>AUWpcG#_EuoAuGCex@};H} zy|r?w_SWU)w!2(zH^p)-ZI;`$T!88u83a=cBX->Eqo86)4gX&U(OWkL8}Q_5)t~q+RhCJ?w9<-)CArLEmzq z?^|^Av;d#b@>$jV8^!kN2}^zpxeebkKB@O#l0GU5_4|MN^_O3L`C;0>UVQoG#Yd_? zpyHzi->UVe(Ur&-UtJUz`#di8Uww)mUw!%2#l@HVCU~~hbCN#Q`%U2kW)}}G@3H*q zL9J(cySTb={+y`Ax3TEAw*7;N@-1e{SI@lOql?>zd-T{;-)4dqUltE$^v6C7-;O?N zLh7e~T%HpQ!ZySPO>+z_9`M|8o$a)0RjR@a4>_?W@GK=YnPyhExGvM;>CRE7#fo*B zYB4ki&6>6t=^54y#h7BGOHYK4GgoqtF7^>NMH{$5IW7sa9mZN>^Ei>d+O&{0)Jl zTbx`S!sP>=qFdGrR-`DJIu)e`E&fM;TReU7KmFo={9pgUe_v}K_H^FjnjFQ|WrnZw zEZbtL9P6`OjcEh$;+j;Gf)`z}BeM)cRq6s=X;&K!P>HI&sM9S*r0NV)Wvi^n3liI) zxg(yfGHjJPtoOSuV8K%_Iqslw#0COYrmS!=E@!Myyc{ zF#1cjk${~!nxkHHpbf`2S!i}jQ&pRlT2-;xXu~y{7CJmzt22Ud%rRYxJEV@8*KWH8 zH8{S};VJe&;Hpxs**It@bc3!}sz(&fGQ3FfO-c{~jz6Xtk%sZ1m4fTGYczdu#IG1e zrr2h+t#blX6)R#*q(zXI{c*R-bYVVFuW6>mRoJ&;4PO6O=?S^ znAbvstBk=6wHilBCxvW$UdnIqfq zgTQxP!!#@x*)~#Clk;JtJ2wAG{A?P;n11oTC_=j{K`L1a|1zq!8YoLt`!!ztLG#ooa!y2jD*h0Fc zBgb-F%^H!KzGEW~d8XsI4jSv4?hG8=G#z7X>9*^Q9M6R-x@Xzu*i!n#y&8^hjRNGl8UhQs9?@4r2IxG11r1d25dxXOE(6_i2c`k+G{-Z@+H>IP zo(Ce1HNzcyhHDR1Yk+_qX#=C`AZKVoCz=mN1xY3>Allq=% zI41HyVwe&z7LMt=f$BPrZVzqbqMa$Aa~KL3Rs#kBS)jG8I<^L5{g%8unfR0?(^XmO&^b(MqJj(K3X|C$ zx}G=mh{MbuL#H-^DQ#-7$PJ*x9fReGIekl2VRpFA$n;d|55M_ZM|hxRW)a{xa=a{1 zM-%MnV|yHhe&i(>Pq44g!7y2fg9XMRj?!Q@4?-I*q%jT`lh|=_>P#@ULOeFJFi5pg z<{Hr~vzK$6ghAlGn>tSFN7#zf#1EpW??e;iS^6RvFX9r9y-**!YKns>8N?~_tpyII z7)|C@Vy7j-$P6)pk{~Yq0!N^ZJlic8zZ@Ht+f z5=BtWk5fBD)*{K`H1 zqu^{3IaATu}Y@VVp_PK9tMjH)Cm&LjxE=T@NAN0K8|&B65!mmXKJk+=XoCY#$WF?$Nt&B5VKZ#m%M`m8*q@SE?v%pAZk(Z5!<0N#lRfH!nv+#xIqG^!@ zVB%?$AnV6myy~i=u;Ipqrco8jdX6k7gjIt5iodA-zE=GHgfk0ue!+KVg}E{>r!_*B2S|yIg?t(y@G@=ne1NXyN3uK##enh zP~<*fu&e9F(<_0{OSo?}=7~Z}eUq6TAXX+En-0v{EeHlNvbX)$Q=^fkT z=7oAKF`?*Q#e(zv?*3gRZ-+p zTW(gDOSJ?+w;<7KwNW+TtgW}oR$CSutx$TzXj<9Zu9Zs#SZXV1qR84(UXl>tr6NgE zQEp}ES}C^M)fQBNzvXJJUCMHQxxMTvrK)U5$WYqIo8?9V!^v-dH9q|B=sWrgNe_cp zkNx%ceC{8PZSAV+pBiM^>+1Q~kxsadAJ%_J4|}|+s@*+3tn#ra-6!?);o?2Do~~i; zUn4SK+uFDh?tZ+(x?{P=&%C+x5&D$)+^1Ljwhi)YCPtO0ShCPv_S!Z>rz#@2fALipUfnlHe1Bd_dna0QsqW zFP^CO)xGYXwC%;C;)@5hKiGZov53=s5q=r^>Z+elu)lKpp_n?) zbvq2-kvOg)u{otvZ+64RA^A5qA^4NJu84_ z9Dg!S+a@XjXrHgtUs1;+N@)BK z2b|BeFrMkUpqg`_mUsTCX$@+D9i8%TonUs7|Vw>usYA_e1)M|xmjfnIDvXw7vy(si8`QI`emge2~}EV8EGmo zT>H3ASHY-!xB3R=ugHrO%qX5cKB~8BJP%@Zs6#;DH2Xuq-Sjb2V;UlTSgWz{`C&lF zibOZq+F@6y_NvDYiQ82ro+CjnTA}`4ixO&wV}WTiBbNH~Tc#dy)B$6=jJ>Mb$sj+VQn&Ww{hCJ2vG|O~ca}@ZlZ|aU|xhB$p zp&tMn2f@#<<0EhE0uS3YEgKlRBx;3p-xDYr1LruIG_}jOr7IzvCi9 z8~ZllF@zs>*Y*v^@=V|MV6oyEK0?mWH$4k9&~3|iw2|T3o()nD9F4?jd|NdfgUEWraSR(wt0Mz>CW&F0 zgaK3}HbcG&yaNOla6R20fQl{xW!5d+NNjoq$-j&ErW44&tbuukBQ$TYB#YQpTZKn7&$KC-}+broT4O4LFs3g(|<{u-lB&-HW z01>8#K5}8cs=7x4iDO{u3}js%=_DX&x`wG4U_%Js55S=7l?knc=v) zrK*PE8pN_hOV=eqD4c8aF!Mqbt0Z(n z*VfGNA{qsnA7T^xriQH?pX*_WX4zzXk>m-Ur(XQt)=P}sWtOB_jInOTzK=ggb8k}U zNq!zgTAq2>K~9*Bl8FkRXqdrHp2W62#WR#dj&T;@EL&L6i4$ReQpUm5OopLnSrLM- zgk*yAD4V=97lK+ukgG0ESlIJ4(H(%=R?cKqxWfSCPC<>9%XdNw*MyZ{B? zbNzHRjjhGm#KP%$F`FdObXj;M9y-yxES!Yr7^isZE}|U!k)I;Vj>j&>er8Wc=P(}d zO_t?&;ZOYK#L2_3oX4S)r7)_xKgDSgMPW=PBG}t0ITbe6r3X4%{f<04D!IP|n(Y?#SBOg(q* zm*;q4WvT08H$@3fZ5$`qn@t8I6=uErJ`|u4vN-SXIkr_YCQ?P2DMLvpkY)=+RY9kXz3AW+@pIhk^pA8e; z4si@>Tj$y+43ZqUO>Jksh#V7}&?FCw(8snOd1h+jIhumD$a0h1&fN%?D9WOtJx9^R zy9qn}qd)rQXFs(6#)raAw@&ygZ@Ejn^~Brn-^3pDTPOVZCiXFLu07{bw5#iptJal6 z-+mY%*?;TqdGvQ-irBp=i>^v{?{+aE+nhcZ;o4Df9bhqU-zV(7=nNEF1?CZ+zYncm}E!VE<$p{^|s!%prdrhIKR<5ztiBhi|L)%_BD^_ zy2)+O?=D_(6+OAKclsa(WK16zJG}`58RVL`6PHjp+^;p>HA}9f5AK@Y&@Qm!rPDmU z;(ujf>pGkgO|4z{M7!?mI?Qzwu!#uU-5d9MlI%yl?kL+2$z-Je^iJU$p~knvq}|rN ziTPX^=5B&mBq|u+2}BH@-dN{4cyt$3y^Z33_715IDhpB!jP;aBuWei~;UwbY8u@@DJQrK~M`id-tIOGzzP+e^79Hd0q9 zB(lj!>5m3q?Za#>tL#bQGOR!Xs!duvJB%2J_R_R3P~ zsU?Z2Y*e+sk$Qc(gjUW_Rk0$0n|^V5w{L2-mdU=ULfdS5@^0hW;mAOE0l2D0AZS9Q>5xY{pM>lumLyvfC+7XhlWRvJMi3rV~`YDKzRUl0m)nL9!ihdBA}>rGAI}1R z?gZFRNzxt8ap>kw7~wFP%}p>_0fuyOw(w&gFpDw7QIzJZ8xYd{V*nxl_>VpaLhcr3 z2o{h2)tc%$2`xZmZ5EN`{C?U{^l*K(ztp;)S#-OyySIM!36IDd@0M@*lU4SYiDWhF zUJIJ;*1O?@l%z>a)}#5|Qa?>^d%Eu7ntT34S9>MFgW~aSJ-L@Lb}yIehRxLq{C0&& zU#~Dv_fnbOUav5J@@c6|iRXGhN)wOTZr5s|UapmLyX;Fnt?X*cuBNE!s_2qjoz>-K zxm>H|W?e3o0v3(xTJB5gT7{)%S;)nuwCRg9Ib z*UA-it@W218A{8QvhA;wmD*cMYIjqvO1bP6Ajfi5kgfNswp^E8x!={))so~cZOVSD6CL7BkhUyqZ^6t8E!8l=?NO`fz*4w-Rpg?{ng74 z0#EziJMBsc^C@N@%<#Gu}_u%sHRT9`B(Sx>W9(n#~|%( zg~tf}w$)dUN}hWA)Xws+_NqOXbn zisD1VUfi|1N?ZEsme1X26?;Q>+xJ%wo*%#cYWH_>r^UT}`Ow`>0@KAsahq>WNYyj;b?Y?ssXBLRiF8dlXueZwZ)->04$o6B zs!Aa4_^}(Q1YbtLJ1chnxB;}~Ww`p2)>PJ7SoE%jD^tIHl zv>G(URE051$$gRObWyEFNrxS!UTGe3Vmlu)c9mC@rY!P8<=8l^F%-{rX|B!J`6*Ye zG=-zaDRU~exHbcqswWkpD%iCi#nPh89yO@r!3(O=9*7=G(=1g-hZLe;7_Y@zqsETv z|LIA!`|6^>@l40#x)-c8s!^8E*7<09EWE9c{YsZ+-!_k#W=p8Byja&N94#_5SIyY` zP`9L-DA6mS(`-_2nBFnPa*bA{sZ^*MKkU*qj^{hgmlff(LJ2&}Q3LjLbX4iEsEMj? zUUgq70{yzmb8fTs+hgkc?lF5RMy#l|1+~FQhqXTxD~GbtYMeHjOoKZ40VN9c#v#wL z+zXL8p~Npv8IGe{FB)$LXEaAkb)hB8jm5EAq1qck==9nm)m6mWn5s8B+)<^@uotxs zEs9{NmRO~f?okW9XbyjqO&ip!#w+e+i>n^jk64#>N>8Y&GR+9b>|y7y*3guLKV=Sh zMwH&Ze$}Z}g_kXs4*H{mqc2DGbN-lRxJtljoM>>;%O(TBx5d5Tglb*Y>4Pd&_Uo+! zZp^%4-)`BLDo?RZq0NcCmZH39)29>W;LB#G@+!BRZ#%3IissR4oo#f7T!VKhrhUkq zzTrA=*}`wO0LtYwCP<)HG{U+F)LD+N(qUU!fgeJN?Z=`KTRM zYuxYEnZ|!+RF0|kE141-_3AGwzxC5^z8+|!fvbD2OZ;v=Nk`cw6zPU<>S&iK<68mQ z`>gst3IYU3JqU)o+!n)g0{*1W^BOlf#>;wtwVFTibg}Y=mZ+syR8Rg zJ3agj0%Q_rU*H;kKr(XzveVwTh!{xI4CFeAO*UE4!wOgx0D?!p=i z6p99JBxU}=Z!Q6IwW0#3a$?QkuFUaEEf>BvWF~{j5_i(f0s1n zT>m#*vRQvjGM9n@nLQQ^vNP~t`q_c+g7F;7-yPxrZDCS7V+(ZBK^DU%jljIFx05X( z^>%!~Rwf#H9vFEyQ^@fKFqf{xM?Oqjvi1fwTrh`+h|kv}>1M>4O@_krbqCo4*Y%76 zd{8XS8XDsdUxgi`FglL4AcQ$L>I*&>V2-Z^Lz!RvXHT|{VB&Zc>Y z<9t!Xwi8EZNj%BU-389WeD3Gd367izDgu-(qGX1X62(R|J;zBl5Ab|4$N1fB5l_!% z=S5_D6Mr^)AG$c7rs#`2cH?Efnl3XG%qRZ)!dgUr6kv?QvuQEMXI?nNX^ujVWQpJ~ zO|mQvf=QlYGe{YEB%Sr>QZOV2|b`YFioSkp9|gzuASe=`Ngw;f63T;cDa-v5Wm6 z!t*fH@C?tgEKjD17ZxebTt8dJ8O|@JUf`BV9N|dC`V1uZqY#%kjl9fB^SA^R-Q@z~ z1W&L#jd2=B#W}o>y?Gc%z+#H0UXrff1FAktW?^pOb3dG7>^nskx@qj=CA3*gae5xa z7*F!aI3Nz^7=@tT85k^|xRXihCuhzS7om9;6!_gmHjCzX`WZ~16a{&T7EwIAh|jQn zX3vYslo-~7f%noSj#6?c!Z==}t7P)o1Y1dv;W&C9`zQkYd@(gqJe#>hrW|`1tuUTr ze`aAXp5xiO44Vu0^Ep@_zY8#$B|$NHA8GD*p3JeGhCz&+)SHB43;)!`?qV83`#99G z@8xG1#_y-eJjPzI7>|SHVuIq-%7gekKTlv%6}gX7D}o9*3qa&N4AKesd4aH_r)ZX?sfXW9Q*4Aep14VA z1+#E!Ph8|q$2ie2Hqp{a$7fz<2j|7iE#}$KoZ$EZG$*-UVP<7+tfgn#)Sn|5@OhBF zj~C;cAiz)9Z+>=8-NXR?m$OA-SO2TU*T4Vc;y+*f_$mf)k8WM-lUvXBb=kEu|MBkX z9cj1z_6J*;cMa3W-u3&58h3Gn4`d$2=2Ov!{jKiSqpKgIyB5zV_L#!wQfs~i?Psv; zk@=|N1DbrmJbUy&7tO!l>qGhg)7ycWMAPKyZQmpg^60#QecGQ7PwgguTx-yJt$NBv zEmy@>ExQ|~=t@$r?8@+8QTuAS*_NtS^x&FSC|$YVU#b0dkDRaED=v#-t1bJhb=d_j zYpq*sBze8;t=H1JU&=~xDfiZD(Umuw%dWgu*WIqV(Rxx@sw5VqkVs0eTuR#IMp4($ zncP+TU9G$9N$c)<16^)=P59sj` zwmTYMza2m7^~P;GzG-uF5yKdaFIG_qx=(gVwJx4Uz4r zl<*G)o-&$$iLUXrcVhn~b6l?sx>WVu34g>2O?FUCnij1r^lIk?&mQ;aR-;*=Sc!Q- zHCy%9Z|Jne$wfPy9M&oBP~gA+Qv8MWvUSRsO`aXq z%2yP9e9Q?v%N}-*YgDcJhU$s07`|SkUh?e87hJpfTTR98&_1d3_!CUZ)451TC4 zc+r6$*MquCqjpcNO48dy@ilMTQq@pia1D+%+LhN8!91l}%<$`RE9-PS)mOE~2}4z- zu5|cgkyj|{#Sad}Dq4O~QC_;$pw)QY3s^ABAy*ZDt=6ouho|jRrhZcS-Fk;t7^Wh! zgG!z2cip&AYc;6qYo4hv!4c2=rfAjqHx0hp8&UL6zxjHH{gJO)C;;eBoCKEZ??AK# zpq`v|XCc!-Xy7{zB8T%02E;#r++FC4_&@^JMxLV)&xP**SSQ<|Of=GW`guhs@#5y+Kax zBTgXr7IDZ{HQh3i<(lf)Qh_t@)UDliCXmD-Ur2$k6VHPMQrLz=d^#X9T(ow+2hhMC z=|pV!W+E;U_?kC&o6St*?7omdD2r^6a)O<=gY3K`jxAt^hzkRaJ>oPY=NkINs|DYN zrstB2$o4#7Vz?^VNM%}ARscoOFd)frLzisfL#B;(otV3wX`~LA#npCdI{rX&kVC3? zmTMctW#N~3>?ac(rZZz=O#rT?GuukcEGPi@PW*TlrgOZQ;G&r1I9dYy&WbP&$6*xt zd2p8IfrVoLt`lrTv75(eIm>cD+&G?`>%jzYr<+YvFDMr?Kf(aU0j9?nlZi7)yd;U{ zu7%UEaNhyg%hDiTgcEZSp%CM85(mq87Q5ceA)Z6e#vVusf6gSF<#veuGy}Lk^%I<= z#bRzFjH5hB0a&An7bdA2gHZMn_&A+hH)rXDCXt*vZfAV1~1im$*sn zV>`6kpguTp&LV0Gwx$e=%1LXFdasm(x5pL*nlV(_oP#69*6i zE~CZwke6eOrorb)nl3XxQg5(t!GH6!AO4%{r-R>T=@x2?_dv(vG_pH<^cZQ~D@h*g zdUzUpI!_(6^>kGN(=q}`9)gsciyxwWD4so`){dUrr4c>k@DKw9A4(XU-kI?!$sgd# zTNFiKqo{w{xI;|pHH!N8KM6%eY2*e$l>I13l8lmNg&ex2Y`5!;veY(;(o>eoN+YRe z>#njTM^kO2?q<8(k|Vx0@^T|>R7H_4C21-5H<#u5>X@sgwp}Z$wW4nOTS@Mg>di4% zeObGdHqr_JTLJJ1u$H>I?60<}x-GZbT3&a{OTbDB0IfpZZZ82?Nm{wl)Rnf~Za2!7 zfU;$O(_NO*Mq8@VvRrM~P(xlVmEN|HdNOcbsXe)OS(LrruLcKvN8g4XqbB$ve0G&S z-mUhnM`*!>e`I-Y?TUx@_k-*~fG6o=P{ny%^wG?z@t%D5E9>_P^xN7`i?nBoXA)aJ za5j~(FZ+{PKC;MDrZ@HbyKSza(vyiB*L1#H**`us=Hfb~quABC*e&>?Nc|IRKkLCeAWs8fVxW{0JkH{~>IXd2I(b>Iy*`nJ z8pVl#W@v_y8LH71yL{`Iqw3r%uEElL>oC>~u|jXDcH=Y^Ds;15?eJ2IYcK-ObSYNW zcmb}zJgik3&01Be9<)UEm~L<#p;4oFnwJ^1Rjt;m9lKMhyiCHMH5Nb`Rc(unu5eJPD+Bs_hZOswQft)OB2#IY)C*ZS1{LTjeay5N zmVYZN^*Sex#K9}3${trVp{aFDks$}?h&(MYeSxddEDL(E2QONcs!$cgM$79}8WmQd zsne!#ES+?zTBr60oF-P8H-}AH?bX@Q$t(7S5d0PDNaE#J0!NMp8I6XPIwr?|TNT;?!pA;=P7ycq%gC{}><)K_w(^ZIcZ_mN^J^QD>xT{tU98w7!Eq9MqDY|?m_d_ZIwc`AvYyS`!>NxK`5DOR&XQnalY<8q(R7~pBW%Uk zcT-YxhFuU3RGlo|=VwbinN8g3SsoWT&Xe!u>Gwaw`69=2g7Kzv088lH!RHu|9-dCm zR+Hcy;9|Cja0Iw2nH1@2l3xT_R_1szx1pw=1W}MiXUoKkB4dS}5C?d^Fq7Dty~F7O z5Zx>f=Vlx&QmA5@OO!8W^DLX=$qoGZuUi0r-ZXFE&!7G4m&M=vZ~w2wfAH`Ao#L-` ze*4?NpFcl6u`T=mFZ9fj+qd*F^z`ZU>_+$JDcWHkBwR<1qTl`ctY|;RJpbpXW1iFx zeiXvzo7!x&?d3+>^o!nR)6+KFo>KHzy;3eDwO?-ga&NnY_i}lu0QOOOk|g&pmtDCB zphc0S?g~&%(c5m+%cXkREo7#pz z{5-zk2YsROhNe0-j;CtW2`4e4a4JYt3jku&eDRuVamxy0fBzq}DMqNu^kRH4@aTHI zLmeGU9g%AB6giKRqj-g?X`lTqzT51GEC422sT`}79tF^@B2-w8svJ{HlV!SZDS=ib zw#L7x9tkqXA6Hq5g$~U! z6w9^fUk}*dVH%Y1uL&=CYk0`X)%NL0<%FV{7yRF66}I*}2SbXXPP?z0?U&u(ZoCms z8Hty8swx~(BlRG>;tbE?C)XwXN%_c`3h-_Qr-U=_P6xBMZiPS5$&CC4TMvG?!rq+9{R9~_u zB1LY5R~I;?E?Qi*!itp63Shjm-}`TVPSId)u2#1Mx>*%PmHxMW!FC$W)(P{5s!3u+ zc*E4iL=hXuRHa*yM3xaM?YDBmFmF#d`9(uIq#2<>GgN2#UvS(hby#I-o24q$lCDuI zMb#=z`bDjNY;oksNkrmOmOk30>$(nduJe(7av-4L5@2Hh+VNcL>L5W^b=0AUTsu$! z5|JQNfE?S<4Y=xRNViEcvAH|BkbDQ(L`$nrrSk7Vv5a%!Zb5hQ17z+^Cni>jl6wE8YGM$S}3 zhOHT653uY|9q;nn#{n@62~7I-aEMf}gQ5G5O77}5_Dph%GneFcTO{^qfPm)J*$+Et z9PCn<;Sn&WtJ>~xFtD7_2>2rdps?q zp}F(o?Q*X{Z~(^Sd){cYiYm}Z|9ASDK-X*mTzI>k$To`wM2 zr#a51V4+1eO>vSKL+kweGi>{jwFtAk%%|ycmiqo83FldW@Fc`x1Tc0LE-=^va5eVJ zIQa}fH45?jWRwNd={!FpO(Q=fE`@jk<9U%!&!%(jJ^n14dqq^9WyS0~OS7yfZcy+4 z+yT`4zqkHesP{Tz^-Lt}6Y1e86*u&WTp#8?K1Yx5XY|h<{rSd$&@G5&uR*l&1c?5p zpA4eIAkKairg22|w98GgRr}rUx-0cI@}`s(1px1A2@v(_{yCT1atm+Easxnmt4Sop zSZ<`X1SlEssRDSqx0Tj6x6ru`FBVE!?81w3QEDq$>uZHpY&QU2K%u|o?lwAoWqB1} z1cbbWZu`Zy>@7)vQC=@Mz`HN6Wp&#vNqiA-{(9S6b<0b&lmO}9i!ZLUC5bN<+cm&w zsnm-8vXoZkwk$5?CDiM0v|_dDZHun7f?n545?_?R3orgfqeu98bc5^kTeM~F0pnZR ze|rm(uMyn?ynPSn-2ph`(Y4#sdwo51>cNwD|MZ|#oHt${xIo;sfb^XvcD`?AmP zz~B=I@G&&|>iMc4Lyk|K67U3EeiA`{^qv$?IRUPo&hJ3-BY1!DQOJKI^UYa(7Z-aQ z%J=y^io||6llCb|KS1Y?N8(1JJ2ZZCi~FkzJLF7$6B+Sqo)?aqFO)y~x4FZ^Gq%D3 zfaApjO0*d9kaj8nq1nm-+pKF;jb-H;ykE!_p~iD;ukun5Y5tfWa3Z;b1@#$2Q?F`N zjcZUXy3(v>d|MdqU@mu9rC--;V)Gp<9}6t=s!P+&%HiNe_2d;(5vs@XL8o!dvwTbZ z!LnARgytK%Dpx9OM`sUu60dg|QEDpnX0^#EG|e_^48@$%tru*KWBG2S$w&%U9Su9w z+qPVNMf3V0{d-5Jfaw7t*ZS~_U*XykHTW0Emgd^4{waT0X?7`=YD%4!P?H4eu))=i z=vQx>l_5t}2SQ7#%A&(mTY$X}kA;rbk1CYN|J4pxp?!*KG*q_wg}{$qzpl6b@h=XV z6kX6%tNnudvB*+FRcr}wq~_aBh2hy|{Eid4O|e@Sdd&CO1+;2|imX}zs9ovMwN9Ho zJ>m~u^Wt%<`Jy4zsLJ`9gKD)DYcvcJPszgA`hg))Y@6d;CjHA@%!wzJ&)-(vtk-UK zUUSVaUshgn!fGWA-j07xbDwv9on~c8dei*!K&F6wbclJOd_Y?rlT%Tl`>g4_m0D>Ib*2fMg zbp=hYqS3yJETpN3AYyV@B&n>dK7hq{IAv-YxvhOnlpgd2^ z`3TVNMUj(~QCM$G(m6Sf-33&cT_jNP9iDs^IA>mxc_d&PqPQ?|i8Eu4CzCl|1mXKd z?0D&P5&=s<>u!#V>EzwqRV^d-Tud@~=Vc07x|wSyIGB}sGSzX8CN7?@CTBRA;Vete zau7YtF6IC|@x-4@$@byJvMg4<2OJ}StvCV<8zu7s`t^cI5;^V#E@q#{IgY21Kba?! zdE|t4mU{^R@N;s{fHX2g3*dGZ=UEa1tI0G@Ld%PW$q=P84~^{w+3=1dglFLlQ2#8( zsTajy^mp*eCSmr8W6cAU&p?C}T69K=rcFZMRT5kU1?=`Cfg2OVhyp>GxFdrNjUmMg%)eQ7`Dyu1oJE8AWv0ZiVD zI77iDIgz~&c)sidGja@OcdaO^&E~s!^IuGQBB}R2mb;>-@Z6^ajh|1Kz0b({2+F-Z zOHR9EannTG?IOGe^?QfwJx#`~*q?H+ynh4Tod>l)oQeF2TPmNh;Q0AVAEEK1HxKVU z`jBq2gP#IrA2})RS$b6GsgUhgAIwO;=5x29@}}wy3?;GFn+=Dz$C5qE>HN_tXdj^~ zG+#X6_~Fp=Ct}|Z;QwzQi+_9o;og~jPtpz}lV3uyK~+zyv{Ds?iVN_#*&yJyCAP&5 zIj)PPs4CkOXzHZf6aPJmufJqE41dV9xMmxWq@W&g?Kd=2W2*J$8(>joxh~sPnAb0k z=%boQ3opOAwf9_m%KMI2E`9pofgH5ZMq?MD+fGv`np+Z&~$JL-MXw`}XM#w8VsJ~-xu8c$OOTR#$+`j?HLQ`|wF;~H9}TBSLG`V*S1 zRBQB4Y9b@@Vx8sqT1`BZ8TLe|Yus;Dc5!7yPQCXDjP)#Yms$+4%^8v#2Ri<6;1M)S zHei~*r+PjK`66->SAYfvN#G?|5D+i&4YKu64R-j}3~T~$P1Q$Z-5isX$DH8mY$kxB zhCa3jjPlY8@fk7F36*+Dk+9Gh@A3e5Hw1lKY&&MrLIG^UD~Rl z*&4Emn}D3E1wstqwKYVVscYK6L8hu|fS3p5PK_imO}4b^qut$?0iq8;7?WrYNEy(q z3-I350$m@IO|jk(geK-CiP^w)w7Yv?FeLj&gWYaZFu!G?t9OBkhF6Ddks;CT;ZO%# zlWnhnn{`henA$F2jo>GRv;Zxk6^U@8tHc1ZGj_NG;a6$Uz=WXVGn8gzSLY0{RE+b$ z!O_G|CR2RA!U)Bf5 z%kMEqa2`ZSlyWMP!It!7r5FN2U*A9jrBacV;$e{L7OTiu zN4}Mjt0>i-iafg7UMZJ79HhDvkuR^ugYu>~EUGBg;kX=*#GC$jb8{t%+bT-+a&v`M zq}3E5Q45*em9eS?0aRCmvTDxFh!Onc>6Hzhd&ezhCSHf%&mp_*Z!Q0VeOctI8hqZDf0qIG>~m zzxdt7#op7ns1(;nym^-){L7JF;=TQiYIWyNUtK(RgW%cN*2nz$&?Wu5?OSNQ-?Z0V z^{Cm!SE&BZ6}w9`-vAN6!D)l^cAIRT%7^5T)|gryXqfC%Y?H>>#R*blIOd&(^ZOid zTKlv~9J2z!a7}`vN%pv38#G!J&Aj6&l4;Kcnxa~iAT-(2PDB3NZvB0uuC#cPj7Gyj z8c=`13-vL{)q8a@p*W6jGb8c{z?>vMu(cz$bI>sfj(=YxPTKro|A_6s6?leVYb@Vt z)hJv94k({!0eg>$w=FWV{iPde|p`XO~P86Ek;yC%c*xaPsO)@}5C zg3?>lHyvSed`J@G)C`2v4pS!@o!S{Wrrmc9o;@Kt&A&VqjtQ1sw2o+ktk>ut7@p}j zSgH%}NMq-UZF+`c!{>wp&wI2Fag#Rq7$Y)17Y(&U6hYr(Tt< zTf>gUk}cVG1(Q`6uni1~{k%O#b6i()Yy-%70-TI%xEqS20}A83$NTUf*K#cxXHCMX zyKyA%?qlA#M2gb_K0C$QQG)ImPAsM5nsffb(8^mWnen z8;0XmHzoY4bRW#qz}#!80O(Q`F)X<_C${d{ihd_s(Z4p?$bP3$^?V+Izcf4RP@rI$j@TOTRA?mTt7)r_M1E`^Hq$3*hN_cK%A~n z8b)ZoNKIUo?+gewo8?J1Utqdj#Q<^T>|=;L9boc2{IpmU9w6JGr4vSbKtxWthi?bO_H<~4L=){?&KrgU_aJxuy-$sjN63$ZK z(GYz~eBECZagxSoC{Dv%N6WKwv;tf%yka>+DDf7^2rwMa^J3{owhnZiouMQO+;HJp zzeE1aNy8+yaub;ug4T1Z$jxAx#PV{rh+qoyB%irKD!U6K{uuZujOR;~Lqji^ zrTDFwtbzrwb`lk-k30tju+nUqF5)x8y2a=G81VVi;aBka<;1gp!U4ng>^>sDcE;MX zSAVxXn=WZ*UromQ$i7L*!IP?p-)D~(`2?c>d;2Lw|IgP$becv#ML`_hipyeuxar?) zuP%qhsDJf9SuVw^d(q5y%CflK3(Mo-O(|ZM+x~U07>vf72hq%nZk0SvGlp`FC*T zZ3?QNVf*2~p;$lTV0|~9^5E6an!uB*AH{@!!>`)>`sr`mV<>(W1#k7pi(3SIJpn%M zuGr3h1bMG6h z#+=3!*M4_IG+Se;!81$^CvEERWbyuxG%4Xfj(US*x;@g!`XSLi=<#fqIHisnJO_-+ zG$>AEiOxVEPkN085GIhdK)oee0yE)<6Nc_h^)5}F3WM750b8#VO+jp&2z{Plo3)bx zOYrqRuq;E>do)8+Et;SRNjPN)`mYBC(I?5VpaA_+2SS%38pN9+$<)Z>4|R^Ax;{bI z+8i&o7^cpUT^c}LXv(c4;iAR$djvD)FAq34$`ex+;P;TAoAn_@A2EHhQ)iUHhvtt* zZ3?;;*drJMP*)`eBuySPI}Ng3XX;(HMv$$ZR%?>vfFLQZMoyZI8YK{Tf&@!8d4Yrh zjyuo^LBgIv%Qjo*IR;>t<4BsTGZe)D^dGj!R-?l)>;W(}%}^n8+&ZK+imFjQ(<20$ zXAfzCpxG8XZUZU%hs)Pkv7}T)w znSE;EMnUh4xz5HWWf-sXPdgF`;z1Outh$GNn=-m zsB#APvH$ec!&-AyaZ0vr*T&_xJkeBK*n(aBawQ7mqDg-BVeMCWhE2@u&eSz@Z!ZJ` z;8q2_T%2mlmI0@+LpZL4WB{#7UX?q`b*p&k+l0Yp<+F|Jce&Wd+=mt8!76me9@R$0 zwobN;3INchjeIn-mMB@Fu*h&a+aN(Rc@4s22zWbTRSbb?!xu6G)^}eaPAU-In4nz-Q^;5qcC^P2)VI`LKIjfPO{}E zOIHItTjpt$F7hPE(-67ADxS^cY$}y*Rygi*7MP*tPV@Q9T(06Iio(#*;iedr5+IW*>XNJmRX1uU^hzBISx$TdNGpHD3(yEf7)z- zL1ziTZ@ij)a%R~&n#XaL+PEB18rVK67k-9J6xfS-=%1?7uwzo|xkMTs3Otk)Y~N*j}Y3zxW0`%(MK2TG?l$-~aV$ zYK=nA`zeMGKP>%T7gyy7`0iHteH=gxRC;}V7e742y6--Ic&n7+@Lu#V7JmEXO|jWN z4j&e8h2P-~7JiE=e0Wf0CoaY~Ju!B~N*}inxtZ7QHGt@y%#2`wp*1yX3^DEdX6`JUZI0{`v>=D*ngy+5-GZt+(jIjH%g_il}^Q|ypDW>})j zwTWhjtv(uZuju2Ic*oYx`*0#K|)YQ%@;dz$8G zLKt_Ohc$uVYkw2TsKcNJ<(P8N>o4+T1V3~341NqLW14HzB;SyZ zYBb5#YPC0Bo1b?Mr55$EQ|AU9t}_M}t~11tIP9L2rD3e(dbXqamG+4>T~9Z5f+G(5RUNbX zq_O=SX?nZFP^zn9w#Ko!zJ^N_mEp~J!~*bBY#dIloJ3k5_s4bzkXovZ3V{!|5QmZxgvoNn4WTq5tP{Q8O}t5Xvv zEpsNCZ0n+8nYsa6WLb`@O!3?&SWowG{%1TH6-Nqdk_lUgzZxf=Q6Vpyc{y?sAZv(> z7&*vyP@<O8#(ZlV54yqk2ATUv-)pK=}W>8iZpfa({yV;eF!z8sN0NDY1TA?6OgdU~jg$6rE&ft9xd5i7XmlYG>pDj)SOHu&m`fV+I z_5s4bD!G3z?UglCUj#R7^7C%O-V>gCLA^Ad~HRkPVnlf>Nhy1i=Y(^Y9&2KOx?8wVI1%OOkq1Tl2M+Fc?nhabKsi z4x`n3O`=JWttlliT8$8D9kNH$e78%G{J1e_k!**gS*AQtk{9JMyhW1&fOIvhvVyYI3IjV8c=IK^Lpo9j1{e)wi@RB&9-Zzi9*84U?#tf}C z4rrF>(J4U>{u9M849Bt!x=x&uAAVplIRp1ezJtq}Vxh4L)&=miD^Fq<7x}@kXHQJW zcP5S|1D~?JFRox$dmz)~VP{%IHRSYraYtOJ;rP4F4 zscBW|t#%--S*~uFwyGNwcZxlVD~IVSg%|D?>&`d_mNjuIRoGM2$v#Eb6jw2FEF9{L zIZ<{omR2dXu?Xz=c2(L4YpJfH;ap&@z6)r!aGGorheTI5Kz$sJ>sq$us;;59uHope zs~85(YYkj1OS-6wQ$w<36DU=49bM5C)0R|6cPvAfR7ssq#mQtkQ4}0*f`Y}?8O8-fxFe0gNwg&c3(TVdJ}fI#x-eun4+c{X4Rq! zY%u`LHOFurO`l2@bW(*~yHiiWJ6Gw(c$X@Na|27sCiX2CZ3EU@L3A9;$VzMrnTy=W z^SNaw^Lc8;s92@859qzNS3#7d`Es$! z&f+x+@_Dcd+ z^?7J5eK)}si_j`aXF6bLIa6_g)if;KPoF#tky$jyWn`itmi#g@X0a9Lk(;h#ZIypq z%(QdIMX-H~VhMa~y8bG&y%hP&(w(XCBFkdSTcCWNr`G4BG*-y*i_ndiF0R641hEHf z4jhZDaE0OxLcc`|AXXG2&qpbWv!64}&o}yfv)C36Ok9cm%#U+8 zRizb!eVmo42h+|Y1YKKz;8E%VeKfL+nb(wBGiJumU{eNxy5r0XNsqY@_C3||KA^JIP*?)X{g4X}L`xLEB z>eXl+IpI%<8+pX&>SibwSLL|h+l&Boi(#+mU)~g#S0(&Y3C+N(H#dW8<$7>A9FDi+ z8%0s@1?5H@jkcGAD`h(zZin0L<>h5>dp+n~UJZ-uVP%(>*VorKmzSgBa$IT7fY#Te zO}~FtC?n{nxGekE(CBi|F9+}%yFVA(qSylAi#Nk!b6wTPEpK|4TM?)jm&e5dG%hrS z2(Lre9u;Duwy-^5#nH53my5yApc^zFTlTyoBjoDuD7;f!snIR0VRcmCc~M zzPjw+Y&wV|`x~NjANz9Ivi=IIHOkh7(ug zpJ^se?&*ysQ5q|ws)(-QnG&!lrhHkg`jqkUDZuW2JQ=g_mNhHSGOp-FN7saRy#Vv8-N!$-TAHShOyh`-86O~ z*dkt;@}LH?hToLOrcS@)QoC=rFQ2$}e=%TJY`68MFsR}%WO)6g{?WaQE~<)2xQ1|b z5nOg&>B#37_}oPmg?qkF&ArRleJeAcSE0}s(EUZRPkMcq1Pqsky4VFl7mpHKU);-( zz1N1%cbTm3?EH&&`ZF{Cg3?u-H=ghMfec>Uoy0FLez(u9UEJ!=Pw={Uf#}b7=e~yf zyTLAQQ*+-7#6G{fw{RB@Uaax$kn{74z0`iOtM82GcwS}I{zCuIrZ~SS9&F3{xv8vg zkG&9+UfmnO-}E(t|HsEQN)VaO0Y{K6y2X;Uf~<4@&f*V#q#Go`6BO5|aRl20BK|=9 zvma`E^d)K>`G(_Zy3KIJah;`GJ%*%c3JCnu0YUs#l=m)L|AMU@QE%wOHzqM5T0>xG zlEv5JjMBtM;$}=@Uu$AO65NpZ=QTn-CM6=rE&iM&x&luzH1QKfsI*XB1p};!FZPl6 zEpZFw_>qThPXC-}Q?*)$Xfm|W0U9Q#U4!P5cw*G;#WaV*#;Fe<&$@L+AlQAE`YFpC z;;?3zH}Ri^F)7dzQx%xf;FwF0U9JgO-UCu^a>5zW5m>5AwxK_PV3^vU5kx~I$v&Nr=MUb}HTZo-uyt}y9KSv0 zNv_sCWtyJ}hNc_IAq79ySj5r|qE7LIL&0JwMxZF-pvQ34t`hv9MzUo8_XJ1PCqy6L zuOSCK&RQ-K?_lkpVMp^MX3tMWacww+j(}@WOG+7pPd1@&7M3P~%VQFwy(lp!*CIf$D z1ul{$86TMHqHaPP6=blqt|&K~n@jD<+b&#CgFHTIQd2HJ1bRGxGHiArVOk-X~R^n()l3P6OL- zKI4ZdOOhh7&RzMOnJupv8J- z1pz9pG%@Wnl%TV8hUWRE%w1SkGMgiu+8d5T_bKdvIfrdpERh>})kDu^dM?v_r)RoFH+}o^& z5lQ*R+OQvwAt-+o__po;%!zH^A%8sE2`y(FjjhOayr0Eh5TNaPmG3(F zE|*&3cGcRg*WLEE)sipT-Arudy`9v}JKLUg(atxWi>V%w_EM*dUqjZ8xe}M zmO5E?x7+5u?s~J@$eGyg_VQdTN=Iz1MM=)K*{<7_q}D}eC$@XrT)bFyxA0KP*YZwW ziLGqg>X4RVr+d*}wdGBBCAZ|=ZnNuLRpKWTHJ|px7FTtSJ_V7ZAEd_S!L~3 zr@PBQ=?mzuEoL3D3*C3SxwvVIojlLwtk)7(y-jZ;cRSmxEA2X)^=i9qZ=`MB?p#Qn zb|=d&w$jC>+Y&Fb?sg@v+C=?UtJUdsTAMuIwz3w8U&9zT+m0m3a@Nh)y}Z|1ci_mn zBVI`2PTGQsvfSChh~=!k?rz%`^0w32w&iRCKdW`tmRcQ{1hLauwYzdIw=Y^3*)H$w zHhF6Yn!*2FXVu$oK(MrJ<@$vQ}%;-K^I#%xJ3qrp%bDE;9`8V-rP{%GWm zi0F~4lX~)~?~WX=z1BmbhgLKh!LWvfXnA;fyYz6bUl`!CPG{8Y*Ie?DF5-tr#)zrTI(emUp+>L1$O?f-h?W$|-}Yg|`dd~TMmoxd|PaOgu9xAh?HvOCJXzpDKH=Ftz@oWCzBoiFz~o}U+! z_CbjUwJjz$TV{paEPKCvzpr}!{`_{?pZ{{16>1bck)!X)lk?&swECdn{>oj-FKQKy z$_J7Hv?DFZ=6KIf;&X(twF97lj z4rEKBZK2TnLZ_=fvi(f#^&|6;T~i0-o)^7l=T{w*smb>94L{5M1T4u!kdq&;{)a1f zzE|~p|B|_JK?{A0E0>Y3p~FjgSF>LH%l0kFG-gCh_C8w{=L#WvYGIzeTDuh1-N@HA6x3lxW#`hPk{h@-h_nMJ}Iw$)%c_9gw2sfrDz z#d2*P4kN0;bZLPZ(TJ-f=%Obu)zV3&aaejSpkt=i<6pK=Ru!1CuCYR!sc~Gx5QVnT zaH^#?$082;Z$Bw>)fQ7ZK4Cz~@)1YT6x}H0+c>JwZ*DWm*=))vC?rGtN*b#L&F@d{}M`-X0&lrWr=~mm19q zbx?ZRY|-A6iUM7Bsz+s^^^`|lyWD2!Cfz#(O{+Dlj;LCdp^(@-EH|E3532MLTk@V& zM1=UpfuXR}Vfn`l-J#2MYRvP;jVgZt=a4|vDY}e09L0B7ny&E-$2=8ygs4($invZU z5uVYFQMH^QxDY(3J`{V^fRp7EIN)6R%?r)Dk9kzy830d&qfUE?S ztB5&5Wtu^ZKph}T5UN$S+J*xZf_p=(Q$wERXjBNaXu8b6!%F+~MV)0|wcXcT{H(R) zJBJ7jdu0L9pcXnf;J7x6DwM|_p=apiIck=dFcB=`(Y{ddLnFk%J%iW^;!sTxXjDNI z&pr_Z#1bj!Pb&0Y9vZP+^?AGWO5=adSC7~#S7L;E|39w_9QXPFRb>i27eHiIqEFy% zK}^p>FHc5PwIZ~jpBFXtNPv3@IstJnDy$$-Fos_Bm|+-}qu7#AE`xgLCEOpVj7l)p z4(ixMO%CpT#IU6RnzzUgT|GmTB#=S8r2YnT(q`&Tv%*$iju@JQhJEyms@4u9Xhu=b z#_dC~eNt0kHfzi)`WRj`G~E=QAdzmD-n~NQ7cjG0UGM(`_6R1g^|Jcs$Djk^HL3!W zfKup&KZeUoHF&Yk)72?lc;=Kd7`Qz7s~^{Xnq~hbeK=%Lg?WKa(NjbjX!2JYTveG5YGsISXNF-H1qs5k)=HmT*1FU}scg&%mX_Y3B<4bK{Y!Ujlm zp&onz_nd-L938ZC91XN}6lY*LM8S~;L(>gV5C-nqrfI?ftN1#pI8I-4Oi57{hkSLl zh?=hL!Ixl9(wq?h44E9sR2`L^k>FIpyq00RGISyJW!umt3uevMO{wp=aL^-@=@s1( zkt3D#O*HpZ_~PqGpn`5meY-fXkO@^yO#!_v4`xR;h)SyJxQ1d|W`AVa1IO-BkgeRa^6`Tz|B6{gWp;VU~Fk%xw9m?O)AhO%WEMqlk~imJ*3Nm2U!zBB;B zf-;o)k~A0&qyhYb-_lSTj)syvf`MJ8z2GvGVUy-3bREJtBJRDfMWm+(HLp5wicSy1Osw5dEIXo~y z)4r-ei$X*4AE-zJX`sW9C<-!$LpVHwALtkUg8rbh23!e)94cf&Mt$hI4@aS6&;pbs zBbSEC2%7gtLv5g`Fl&9no{}^w)YFEBs#>}MmlITmt_S2l^edBbL$yK{nKWnzvnI=Z z4JI5Egw`;_l1@MuZllr2=<6yBLWS8;$snLTs4giZ(;7Mbkpb7zFfC&=BK=6Rq7TUw zX~RLGtyEl6GX4QP(^aXjX)@8OPZXAP(7$gC`X;#;hN=%pHKKtEzf@h(G=NiJT+_BK zjm$6HL2$Rpwq{y3+~oFf1g}Y$6Q~1|)t8EkCXEy_4sv}#m<(!3vSGm8JktBRq!MK; z1zrGf=gaW^V8Ck*o_I3(?WpLFe(}@z94}5W_7XQ7d%<{a#1&d8HT~!PqiFcO{TFsNn$SvJCsjNiq0Im2-ptR_YTr` z@!|^{tl}(QB(d$T=8o@8CT3>g(RjAB{OMwzYaSk??&53`&Ei>li)PKQ9QMhEU?F}J|8=? zg^RzOj;D*%iEy6dFq}%0Nj5uMW?_8p&$97kre(g3(+RdftQ}5%6ySK7Ocv8%63iDt z6#BEpD#FPs#aNk-PZuFxMPXuM{ML4`7Dr*2>Jd!q)S2UPG8zYl8!cy{dm3Yy%K6(c z3Sw-=ahj!4Jez9R4`68i)PXl%>|$q}4wk{2$<$q0*jZXQ9KXTulI0jDp}&wZytiOH zwwBn&dKe~e-sIy|HhnXLs~bd%nSg`aw2T1`76ITCo|1 z%OHuTerzhfrWg@ceLMmcu?hcF$=2S%0h|VSh@}KuaAH0)78q;MJW3|IgjX}1hjZT# zP0ydr)D_lMY|RX5Xkt)ikxkN^w1S&Xft$maE`xErh~F--pW$GZE?_>OyP2mY-YK3h zQV$1aZeTnD$4eMiQ3s|8tI$)dD5(!mB0Q8V1%{uV;Ww!c zcR%*wEE&ANilF^~wD3lF0aIdNE5uW{pg8j2)r9Tyv)MbC@hliRSO>X3B9|NM!zJ$F z(8DY8x`8I)8<@m+B4f)0?H6xB;EG(E1&lkIVuL8|VGYM{_b2-4aCjPl0C-UcSRa63 zT)dDi6|Sg@ix=YzCy`^q&7B5|@ghx)b_r~P0SO?5o^;>=6Tfi|?_ zMKs2_KZQ3Ba~_ca23UjFa4vzseyV{MlLdD3lnf#8BRoFEV|ZbONfN-Eu3Yk_uvq5k zkN;#z{o-%_KBzgGcXBGXPOFEf+morrq<2#fEQ#<~AE$bV}4!=>W z@2%YTI`~+Ili=DjrTG28w5Ye92lv+c&darK?62MU<~`-!Ivd?zZC~zOX7qRd=qC>U zdw;fM{`42WKmO}Ko&WodyWS@MgnF#EN$fl0pT$w^qU~1RY~`)g>a2*b$wepY_Ac7p zl_*L*`66$3ce!-2k_%6hPFEDgyqk6N_NAkVbU{2sI@{iAldqv^*6vD@*jl&pZD*Bt zE?OVl|B~vvdwM#>0`=A zldf_@%TM>GedvlDk>cyisqkFPk4@|s3*_mkfNV->J+LlsQmn->kKI_uJCP^ zDY36!3C990bPnhaBhd#ZFT5A;f9sU%CQ=tSm@kLah*YrR}dUK~^!Cm^=cX6ffV zY8}5W2}{J%6^>EpgGzjWN}cBo9yQB?hDz-!SLtyK8lgkFO+JpfI$JK~4J4p?xlYkS z`NgPJsncz`+o_lS>X+rehY(XauA2YLZ#4dZDpjdQQ=*&YK2>8XC}8Vd%WSoG zS}8xL>E~RXK43Xej_ocvRPP*eEL$zN`5I5ZC<(o13|~2}bEd!^Hv1=slP0oMh7pDg z%hqMSQZ3bBq$hRCsGOD#QDcC_GR=uK0ofFdDoQ3pKT=+X>_ zI^|}WqnR>CaWp6Jui%=@Yb>MnN3Y0Qw5?cVRTJJ0Y};`ibD%n^YDl(iS;hL1qg%Es zTVyp9-hdoqBsuO#mL1E4FEkGPHyn+u%zCa#VA``iPxrJDSvfYz8ndkqRm-uQV(HXY zp(EKLt_+6id2X@zO#bL2$8ZhLvRvr2IBpG858mJ$$8)^m!-6bEJFY=`AF2J3RV6?zK+auL5O;l&!#hXLe?(wWQyO$@8STj(svwLIThV2szN zp*Pi%*c*@Ic#7jN#5nw7HjU%haK}LsBxK#lF;go9P2#aRIXB^uJ&hwfSWJ8qm<_Jr zEC^;eiSgK*W1L|xkMunB!)1Wu#9QFAH!}~$JmB1 z*f<_c{2-4r*SD7=oQ0EkH5t0WY@zyjHkl?0%$pZw(Ad$jJ&Pkh_Ro{4?#@&ri6al= zh3bxND}zBy&BXKL478oi1K0MG+1aU!@z~FUBo4-)*#zVBxnt!y_VL2;*MX6SK2BF} zJ@|uzFrUh49866cM`0F(Fz2&*=0*5CQzFBQ%xLVYc$R=P+fy<;NK*`*y^R**^wdp5 z&rR%^mHIeyaWV~kxPXaa$LV}+1^8+W^f3*k$1bT3jn=NwqA9!%_f&uTL8m+C3Q(SLcZMsUv2?Y<%`Yk0-kKe3vt_7%Q*u$Hb_FCSEpnCC@b z72f>fR?f5bO4{yry{)`zueX4z#FM|fy;ybI-A%jO{eB?ohw^=vPrFV(f{`A@SeNBN zZ2USsea_kWx`YRC@v7{x@ex{GD-YNH1`gz3zg+XmeYnzH*uKBAQvBTGt$Le}K3_hG ze~)0%&pW<;PRM;;st=UqqXa%I{$_dnBz=o=%@Oi3l|Eg0?`~NDFZqaMg(H<`*lLAC zuPCv?A67~fDplVi^rXpCuU@|3s20oAgc9-FYn@RdU3qd)20Eq%KJC&+jQC8TdA?fW zSwJ-U%NpA#(HeTiBeqiGtV57yN(@t1C{|Q}<VI3ALV87=dX5=$|~J54a-^9k*EuB$R7RgKqyeFR+68+mJJ7WG8V0XTgTCgPn(fu6~yhC zfWMkcmH`x38tKFR`@9B2A2}m)2$cYs)qPllLT1=DO%!wUI7$I!&z&=1yVM)o(@_urZ{j!`<4N{KJ`YwN&Z2P~F7zn$ zqPG+1DHtZFX%zUu5(s$e%@z@k+?k&_euxA2)YWh@8E4aUHd_ICPu#N3@ zI|%%AKKE@LMiVSggLoQQW9<04Gskus?wwIiqhR7B#LEJYv4vB-v>p9)lFnj0j%9b~ zMByCn+yxG2UKG9^W1L)3^M5A;HUE#pPf+uBX_$Uwxy5|94VT}reBNUJD2w>;TiE{Z zu||J$d-|ijB)YA~4cnQ=0=c8d7I64Y}rsFU~>#NiPomD2w>s@!-YDri2 z-h9_948FbfRc?WcOM~w!Zv&{VI^vbd7eo{m-?o^yB&jX7R-3}+3y@1}z9gXl5PG*G z0Zea1X)9gqHtnpH0pkL4=c0Jg>8`T%rOo#;oj|L1(Uvyi2cs`M+7hEL(ct2m*;mXu zo9?RH>U49^s3U>q+g7*NhOu>k_vP+xz1_CA+dSJR5%_*k?uYX0FQ3KdEAYDF;;XR1 z!R4_B?V_U(qnR==Rdw z`;hSSJNjOoyNq`G`q8S_1>P_vXLrQC|9IjXmb*Y@8M2>%gm_Hw|FOfu1dZ%8lKPzQlF&tOtDo8%$IR<47hB;yR4qHKVr%cxm zhIE8#Oo^i!OsUN=4Yr1w>l_k!fu^hISxK#x4_UT;Qm>b2hGSZl zMvG(V5?yanHpMpuisRY(Z*hR;495!4mZzs89{z^-n04?$9(#o$xO!pfX4C z6_({G&Vzw;D*bwmue0^0&}0VHXS~3b>R+G(n2rWZv877$sN7_1u~V;6jRs6!>j1ur zl$e7?ji+dq=eVQRPt+RClqlzy0vutFUJK8;V*%#j8P9bO*rz8oBpl42*4tHvKB60R z=|Ct0(*O1Wd(JW?x`Ai}SE$S~tU#Tx)T=s);cHj`$b@8vK!S!lkR9E2`j(?=rd60s z9l%A!brjpS6hqQ26JS;~O#|LEYz@fLatEHXH{ikv&2|X(5`I*PjkE}}DXhhcF(M2PXgX4fJkK5J775sbDgzZ*R)y&?NbtTj(sk3Y`w~nThyzH5 zIhKdA;T4Q6!Kh#~mRGC-*f4hk9X=_c6ICTcAQpK-xO$&R*F4JvRS6f9)eE=+MqiV4 zq8E@ov0r@I=WT)-;eC4k2ehcP~r!+yi@nLj^J1L(dKf8l zD@r{n1-j8DW8y}S0eZ7D9FE5_PSZDOx&|bCXNGR#<1n0I99XWsh@&Y0brjiv%vgJ4 z;_28NM<~_z`5ADy z5@37qcAofYJWaH*e(LE!;O5lFD^NJfR(cW)NvMJAPGX?&Q;-Go9xpAxeZ!t%11FJ} zOwMr-VrM)C{!QZ?2XE}u^C#mJhklme(`s<-ap7_NZLP-N(ox=dtVr)O=f9@I_8kO1Zr(-U|LgGxOhQ_J<~U<# zjJg+_i&aPJweH%Jciokg=bcM~@~$u_?+Sx5VC3GSEN(Bhy^g%=?!*gXQQoa~;#zFw zJCa2Xco=>f};qOMrC)64w{2Ey(V5h&j2p z-sLNxborvak>u8@E0UH#-eFtM<45rNCU(_p;P@Eq{YFK-{p5B}w~{(td#v55 zH@Y@r@?f|ZxzFx&ue@(ilpA{7%hASt2k$E%TYtiSd>6h*QkDX>-rx2lew2mt!Lq#f z;dfikZ$G)+)6M7iq*S^rm(YD96;pOC)6R9bVy$cT`QG&k*Tqra)+u>WmNy?kEy@%vP3bp`afw=5(DhnWLn&Sr;a(1 z;=3nHku5)GC6*PcY?(e3coq#xwaPOJwSdZ)dYL5IU@5-LSXKUyfCOh{1~n>7L!e0( zk&?jHS(f31T4g{B(i5gm(IAC>%Ab_jO1lU8z2<0uMZQLHi0#res&Y-BOC&ISnH^D0 zPGAs20hS(6JS{dDL<>wC2~XM-TczjJ;g!j_r;_BF>mDbplz30t9SVu^mu(oBP* z>y>JaK_!6!cm~Es^|DZ*jwq(|x(qzY@fE(_LrMWs?EgCg%RMbo)zY)qTo>`>7st@1^SpoD=1P=;D27AF$2{}LPfM>ThB_`G z5Pifl6gsTYNCX6Cm?~Z2X|}&2#LZJdy!P}W;5YTnu zltcWNfmHjJDVYPqwxm6_0dvB6M^`n;b}ZW@W>Z(TodR$j)zgi^-eOGNgEXyg6oy@o zK&L{iw042QN(==#3P=>_LOp@p+ zhM}t?P(aqTA_WHYLYUJdSv9Po1S2I5ux|gQn)grM0+9vTjvkgB?-elOBjL#$B zS~nOi<7oVLK8x)0*qjx1R2&&ItS=XS;OC|jSg~i!LhMhbMF2XUM`yO1ICd6=YyXQ_olpFQzOcv1EWyqy1q8;n8{|nG&#gF}xsDB> ztIwi*vYH#-M4stE3S!5e1Ze62z+<4yv&1{Yx*XzD%Ui4l5uPNWa-L6dJYB|^gaQmb zY(Cm#EWHOF~o1-Xq+=L?*6>IaU1;;gER8L|crA59*~9r_VuJed#9WeW3-~+?V>LGY@Z2`zafFSr5#_q>Bze3F z;+YRU04IB6H}-A7SWwLk3>Z{mgBHNMB$a}XeGjL}bT&DkPsjoRUL;c=P6o61)WC6S z+5U_ei_fOSV3L9#~5gsobFL17~`2W=biyPXn1&eQ# zPY3UQv!eV8Wd1W(KFREN$oN0I$2k1Ieho4n2j0)%J<#9B0(bJ=mN+{X!NB4cAi3RL zb?(bMUql19d;7fey;XN3wn)->c`I$&(nh{C4PUbice}kzz6=HyFY>}Ld=(7bDT0Bo z?7}(8r``kR?QC|v!YP z{=qCvf`PNm55d6yte3|?@GXWTUnbPMgnQfS_z?Mhk_eTL53b4kjD_|w&d{Ins&=pR zAAZ`I`@^U|FR#%0qiXW~!}$8f=Lb4BALH=;Aokuenr6k%9rn7-T@RUtKS{G6q~3`4 z{S4AQhAKZ#g_p@nKMmUtX4-wAZg&0IeL8$2BEC=1`D2y|3eY7VZ8UMTMKungDqVkF zp#{3m*AHG+8FWZhd`e)-0@W=c^rEB+fKCihr2w2ovqD4cGC!^$234!262sJ)dZk<| z9X+8dC5k1^%^(YKlj(3Qq7F+mkQd99nuw>vZKn z3zRf4NtCN@I|OxQU?D|wRL3Gt&kE41ZrX)y(j!s0lBp3BsSV`l5wGXMcB$xYVfHN; zw%|5XB~HVNF6o1zqnm}H(naH^Ca7wX_oY1>>wEL>-tijx zB!RBPt+$Y)o3d(Z_Rw^OaKiKy*B%n1=BNN}4It7cR#4j`$`(G}j!V){nk2&|=};l= z!A_C5&>#p(a2f=e#03h)C@{WBSN@^ zfmfvlQ zn+NNeANjsJaZ-1j%+HN!7LHR@N>X4`0B%$977oepmgAv?$Fg~v;zfv!NoFo|_-^eb zI2`+77Gf{WlSobAJ`T@~AP$!}3GtLzJ|{5_XEP7QpgAAU>hT~v52JQXDsfFDZ$;2%RW$ zp_?$YW95w#g$7<*Gdx+@6MF*9CtQfSTd@FNHRGG% z>qAbq-hBtZe%`W2hrxcLd?y*XzNVGd|Hd7Wmfvk4@@G}Q1FZk(9$@`H9uKUpO}v@i zaS#(z?&i{z+ii*4_HJ*=?QPeq52oDCR$i}nTS;DvyYB946R=KBf`cVu$^8%5f3)LD()F<5!j9Wo z7k1oBGwx=$TkpCV2-vn(+ivSJCV02IfC}yP`Z6TA2a4|Z_7cAzkouwg`pSLKI=W)V z$5|Zp>l_7?HhN^{rEgQNbLt4>4<7_qkZk8YLG z1J6F_e`Dkig6mZ+`2)9pV8+Lp0J9Ij_DvqU>CCq&*Ci4c>FhxV>KnGyYqhcms@;6{ z09M{P{0$AV**%XwDfuIt-fz79te9niuH-{b;JG8=7zxw~DxbV)0BxcFifuKj49nMP zro_{za#&*-RHILrpB|MP4OF5I%51ICC<$eXIYCcR{aKZ&B95bv5x`VT&IZ9%XFL{p5=rpwG$TILbJitp3$Wy)1WFP#PwS=YH(!ZlmmLr(q*z61LA7T5m#@}4WYs} z%D+i9%BaF|$Mq+jgCdl!Bm0^r>S3 zmfFsUpzc1um0d8IUN``I`hK4P$HRFilYs{qJW;Q(!E1jva2 z6uJkPBwAcrepOo^6sBvJSg!{F(!{yj)ht~y6B^2|1KqoYk(I<4L-!Iv zbHf-|pljcC`eaC|W9X7&4+om67F9i0vu%^Gt*tv=;qhbJqmi>e2YnWOLlej76MzLU zoJ8+zZS61Aso}XgPOX(3PjR@O`)_8k2y>dZIhUf=~2JU*KTV;zq@yomF~TiZ|5B%9zl z?&|@GY@IGVkhhwiy4X+ciH|1%o+ZvKolYlsF(!td804Qi(BHl9A?;v7PAZo8K7bYuo^_uMKn1*m$8>Pz=>JnW8ax-KblP(KTE^q zH1Zb2%Im~%%Jm3l`idIGK43k@o;ktOAR7WJ&d93De4O~?+K#bz7A?K_eC=w{I>C8x z`gSn`lE!}QO{H)=o*OPa1H_yX@{Tg%g^hz5UVJfj!X#UtO}(^89&h1yGCm93Ier7A zY&)y7a4wTjW1K8tj-q%qaq)SIm!X?PIJU9vO;>&vU^j6AdXsk{K7+ej)^}!t{WO7n4#p0$y502!JSDNMdGBI%kKJ`2l?&CbrD5L3aC#4o7NVapj?;k_}F~H*iXSoT*g3jdh=EbQyH2-Z^%sJla$D z5#>$~-w@d4JMHfB=v^zVrhLTbyYqAN$PIZ4(eobi{#dEV+I+c3U-|rARd4wxlTXH14ENQ`f3Nh*clGYS`v-r>o&5P<%-@;YdA@8p+H{->|L`nSH?{^^kZ2Y-_P?o!PE(O19!bNU}X`=6;2V(C|Wxxp|M zuEx?YIEGgd%Q9WM##T@d0X4JrVhcm6RytyyQK;s!^pJb@sv@Au5p~G0r4yQOQ**F##pFV(7*7?`MY(BZPbMtC5~x%LAEfg)EHF$9dyw8+cftK zfVoi_z4QHrop%n%*&&rpSVBGyVwoiEYA_JHe8fwN1Dz;d;t zYPrk+-_k(YRp4ELDnFx}9NVm;!?M7-a9C&qV|a$GyfT>McBlWMhDsd{FkCx%2EC)_ClrOsQX4d4 zxEfvkjenCngaK3!MznB1Q_nb_u2pHSt1$z_P*12VNsJ+P<>&AmJ*A*fUnjs%|jEs0`-cCXtkH35ZXWvD2stjPndKhg}1>=-tZMXC809!4LbgScEvN78-@$6$@=uZR0i&z7WcAg74tVbt$;4z}chen= zh)1=n0GHYDdqDD56OCQKce1%5OpRjo;d?9j#DK1e3wV*Af*g|eMs&@y6+*`I*jYs5 zvz31yO{ViC^WFpiek(f(Qa6clx|sWbcNnKh7%t=W+@0m8IUdJYcY)MmcjD@i=lY5p zn0n{}JUU7^0k&@Rb$#Lve3#@n#^Z(MnyH!kDM`JQ z%^V|jTtHAKIJdDo3C%?oSjlXb%~q#s5&*=`#yOy7oI0!I?fL06ovmU}$2Jpfn&RMW zVuM^?14a(X7IRLR+fxtwQIt%`j$@H)g$7n#f9{7EM}dKZ#n^Xd-WpHV)5XM8qlrDn zaJS;n!DAq0BlJVE2iEj0b_ma7(*uT|dj2}f&i&IMilGl|2W}pCVT6HI%?O8f@*_=3 z$Hh);bG#e_liPlr1}`@`CpZ9Pj?(kg8k_SF zklZ;VJFP8Fmv-#N0QB=Yj1S{5vM1vlJInbrnyz9Tk`!Fy04HOA=}c$FB*C*_ZmVCo zI2b4COvdj%hVYI(0OghQU4ily-hJK^`CfzYcTpb94gLM5t^N>~``u*cx+l!{)|`9y zZh&-qTc&&Deba-OJ3-t&0}1{%-Sjr_;VN{uX(m_r~9SV(49A{M~kl z^%ofXV;pa%w-x2xdb{3quHtxClDHvZyzOis#+#Ek-hFE5?v?qMWQGRF&2~B2ZV39{ zhw%apOY4o)CH7wu$6FYHcSRuY<|13)4&>c-hz0m#9B*%L0hW7PnV5jPyR0Ryd)@7Y zv?ghxe~9G$OIGf)2g{eV1wZ%O7e5uE`=Dj?Qz-m3%&EiAHqdVUeNf1!%IIq6rH@Cx zri6Qoeof2+Cg8i~^t(g(hUVv6U4AePe@ySRyx&dsQ#p?x#K=$a<=0@(>l-S4TG%IO z`SVGe_xm(m*Xw4RZy09${+gHv27TAEez)p3wYA@zk`Ix*Y_obcUesHq!_u<(ynp)S zP^dG2W!kY{FPDDI4Nj87-)sK$WAp{ZIfwiq$CS&ZT1BsN$8{DRGB5wd-$opDh>&nx z5*WV1Q1wIZNu7SdnoXL{*b~Ia)QKoi;sHVw96?fND3oQk!m_0obynnT=2hjONGDa$uY zwHD$94pD8IZuC(NSd;~_EHULKTc)dgr;J#xBp?9TKH@2!;`nNV0ci(a`lybY)y~sa zgW@aCT8DJ~wNq(Tc&^mqxF%iUUsc(IdbwSrQHf?tBAY!G4(b)4-$q#|p)&N!Ff?6l zGfxhgcAcvN=%ZQ*oiv8cGRFZ(*HD#ha00+E{en3Joq(|^nk_e%!O?HG4-f}jJz`4b z8vRV5p7Jd?N0L)Co>LsflZfjEMKxLesLW7+^0WlK2viO6)iNhAv_P>(M--wd zwp8K}Pt)ZA@O`Nc)5Eezpn;N2;76Mv9q^evQU}gZDR$NCqhNdVZX=KW}Qfx~k1FmZ% znH5#Uy*h&PIJ*9u>)7NVGHHwLTy_N)bXfw97RC zGQT6oRz|AaHvxrpV(f+MKmv0;vSX5I>%^H_CfTdtW704+87SJ2%{~moa6QS`@7M%7 z$nZyYNf@t0Haj-}p4CC$QJuosX}`bHK9YByH~^L53Y!TYPfY-?U}ov_Fb#uzo|0Tm zo@=j?#ToX2w*uQawc>ZDj^fj1=;E-@$ATm zfI^qp3eyEPf-eH!NfdzU*aaXShsM&zX%ML-4fEN2IzPvblSgBJg=Z#-$aSWU%Lm0Pv>smGSOW12Uf^v-!I-oQ|Vp4)i?6)6jz% z1pZFae36em125qEL7ViY(6`19`6}dG4)0g!1N@C}qT;EN)kwiO9^CY$?`G|w{G zSokuaH@mnX_T(SP_%BoW205-iU+!X~aox200k^Lh@at_>bWOnM{=-EXd_sU;G`-vH zBZF=4srG?6waa12pJ8WZG`d#fGCS6NMZSIF()_+xLcdP$_o;skqHh`3)yL+z`h2+y zZZ|gjUEZ$ubwTfeY)=oTrn*O+dkw6QG(F#=@3ko9OH=pfB9xc6w*-CwwwHH;t~`Aik2$W;^9EgK1di*mbd#ZxRRVZppKw57QtcJPF_hS(kAc%Tfu*XY zDqC{+`Z0Wx(%lMARhV}SU!~)Uf+~nYY#W5}%#pxJ6yGkFD6$W)$o0ssMl46sJcSs# zTB?*#hiSH%7K5Ib08n|h$|FjsQ!LLBT0dj?njkRk=8MMP;u`0r!*hyaN=PD+y`?gB z$TM_VM5m1x2dtnn2q_z`UaCI@q#Xe%(tLxVOT)?mL*>BuwJJ~1?|Hp(C^Nv^RF&>m z58f7-r-I zoi>?&UE-);o^v$&yu>hUnQERqFV))RhFfMYo;`WS)6IrmFE{BDdRIBhIiW_;fAEYd zz2p}!bxJ%GxEien%_sl3_JUIRr-J`>h%OqA|LcwI`T-_MzBt912Z%AGzKw*2J6P_+|R2iDBm?ZU+ zWEZ)tyux|fgqp6VYnrBvfDvuL5vMRUlMR9ugHWPjNCmhNX0^z13$V}Lr^s^jeKIVq zhzf=$WWOR^?^~KzCxIO` z-6NX_E5s7*6djNy0FRiBfnW>cvFi<7$r=E2TO?B0v-_50IueXTCwnou`(ayT=Ou+i zCzIlsimceSE|FZ&wni+sj9^4Zjz|%!r@!C`^3Ub2IX27@oFcF8w1eC zHZ0k*$aCVswa;-CMvE{Q$MYzPR6holg0bUIesmTtjNuf%=|(VKjP=QQJxc*e11AI^ zjUyOZ>d&V$e~B?nRNyATd@@@nb7vL@>B@5l3mnepQ*SXOhS$Y8Aoe)4NF1>ljFO3) zC5tFca4=1@S>l^6&R3IVOy*!5`ksgF+)n2UkQL9SM)E~~Jv}tB5{_}0XC4j~b8o3f zfaQ^gP3XhI(F9xa#Pni33>Lu3cABO*Pw+HeY1n-m`x@2~&zf6gLu4~On}qhl&)h{m zo1M+yC1Dz?!EEROZYtO_v5b9ddioZVgw%NIyqQ^eyoe{zaTLs))Q@lgpnbMJT`blB z`{8sHFOo?**uA?G@igj0sHE+rIlK94~G^$J6)uN=5b`>v4#Q5a}Wz7 zv(klS7?WwT442Nroq_s3+4pE>eUUj6$M@oCk`tqMuv&&NxU=)w*%HWF3Qw_ZPfi!h z)y62 zcYy!J?M2=bvtCEutbn|M$iy?y|B-fpGSKQ{iR<>zx+F56_Yi+h0u`A`B zY$vZsR9lsci_XPvC2fH5i9ufO=9`O)&Z^tl zt}}@&U1TdsYPUPNyxV~w5Ve-q8?n=od%4`b0FgOyj9<%{xXV`C)(TF-$f3Jci)_N& z-Su`GaR*w8+t#Mr?aJ`Km-X^qw<~5BytZ6c~riDoAK&}W*-MgB&dq&-sjRVRBokpH`H5+MN0FX5tsmOh&6hj+H zvZA=3p3NKi)=4HIg@l`4OVLL@tFyc730GGA^SygId3Jpz;^A`do>yPqc0I_xJU`Fw zsrM!|#Yi4#=V_ECn+3{Mij#yQh zp5b~|D_FwFhX6~qU|?kkupccOHlVkCkp znUN8H{1GIBUw;4hzrd3RSG{p?{lLYQUr_Ae3uW`Z(#X*@cc-pP58mRR#b60GT=x2k z9}gDUAE_{Wa<-bN!&y|yOY_K`cbZ(jI7*V!{ATAyr&~<6(R+t(@bXLL+*)C`(OF)t zt`wIx?7OALTCwhP*6L2J%wLg(g>7$`lIuMw`nTIhKZN zySY?Yy_;P_Yb$FxE>o*#mz()&xt6P}XKL$ZF0;B)=2o(+C81ngE)p=oUhfi!fQJ##d}Is~NGpT3B^+YkaPu1vR>d-bRh=q>!zaHp=x%d8t_W zrB?0HL;1scbNz0?$iAUBxh~i0?s7YYl}xs_%r!E#S|to~#e*DI$Y%;qGYtj4`@LKd zy)~|GEBO^}{cz=|cdy#r%|CvXTgz4Na$IdQM~7TrUatR_#&SvMwo9nEum^2<)j9i z(PHVu;4<$$`A7MtoI@@5&St69s8zjAXEhd+U760pZ?InoT$W>U4q5s?zm?;-{jAp5 zs5gzy`n~K%ZEcL-VN~9pj%LWdH0>pZ`rIX+8P)!)oWS(s=fD`pd{L z6d+=YW!APV3u@Sc7^x6L9f_t2Fh&TQmWm{LQZY588McW{+riLKLHY%3$&e)vXJ4O? ze$vaxMxtc`JI%fASPW4D^pC8jncOffCe}66R&>pBRLf#X*DPDIPGLfp?OaHKDBU)k zRMIcaF(x1;$PS@~SO#<*vs7dlS=hq5sWTMNwj>8@04j>bL>cIJ5SAhBL6aP0TTEV1 zOI7~_YL}%jSPTMYjHYRVqMHmnGqL6X%Mzijnpm=+O}$|WfN9$^dI`34OVts;swN2# zimFci#)iq_TYw2vgwi9Yx(pB^EU>RvCsl_>z-DNhBd|PeIIYB@K4{BKYv0DyO%m-- zL8+?0BhkTOlNwGPmS%QK;Wt}@mJSR(jpnd4lSw@|ib*ZS^pq&-He~7KY>@iW#t^G! znn|4{XJ?2VavWK*(vqgZGpPq{sGFJvsOd-*kZ9-zGEAKoiyD9hQ8zRL12+GVb>y7J z+E~a?MM+XrS(POqX@V>(f~<<7DAOx+%aUyc=mHkl^fDEHx_VSymo!5)M1!dp3X-g= zOgo;sjL9al-52$sg*6@0$p#2QV2CEv41-!_YETm;QPd1N-=YjLK(s>ogI*eYItl$z z7ua54$E4Q_EPoIUr(rnd+!yj_fZfL*_C8p_6gQ(hpu{y^n1EuM0R2h zLSm14o;!jjo7e!jUO)!K8G``o*cFLK8`2`x_JQFDdkH48XYBhVY3<36Tf}j!Pm7#uAB90v&@^ zg$RIK%qoCg#nT9tZJ-=t;o`nWT zQNpNCJw-?);eBTq?M3}Tua9F$#^ZRee3)qanT-;C&6I`X{O zGF+eZVkZKihkRlY7!5I@(_*9kz#(*0q~E7+LkD|S?5qBPLzvJ=L|nRv@4JHQ157Xq z`qDu^a$Owm`7wqL2^5PUZ>SQ&GQV3+|6l+@Y!8XDM@W32qhWx|Fbqs*n7Co0!~yF0 zrY32k1&Hv9*6RdViF{Q{L_yF<*LMSr^aB)WChDw&~OQcppt6@zB2QCVMPg$9MZi53kXIMgqR zAAS7vC!KQ~YVH13@}D04gT24}rkDJ?-`&0ms4i+wEK+4|(sQnB52oaovp5jzHpFl7 zf-78}UfQX#P|r$R60cl-TiD5q15ZxNtzd0BtQ7mah?!Y5?KEV?4KJdOq?aP4Y&E_} zeZqUOK%;lnLEaZed+}|y#8>{jtX#{xU|c_cM$WoA-T$vhw8$nv{QP42A^iX`_VVGFTFPUtMyB$R62uC|IZhOPa}tAL0}Y4uH7E<^OLqX7WvMxc$l;f zTl~1wQjgWc_G~7$+wEh1dNOZKJIz+>c%HPT$#_1WF?EaN`1r6hr?q)nr!{T2dA@Zx z>+! zV`#MwJIzjeOgn40)TGto=hIG`pC2~Ie9}(%L)!5yna$?3*KzBRw%VGfcr0ryIppW< z@s#f*?aoY{(n_7)~ z$6&d|vuD5{I7iL2Ymg(bZ)$(s2E1z5bu2F`8SKdISgmTD61yZZHBx32F&n5C@Z*_& zigwn_l}oR_G{D&~Z{yYJ#x<*zmodl~^my62zR<$yY31w+_2TK7x%y?JH}F#fTo?vz zpwZV?s{r$i;Ren-yQsfVQ9YYKCU&DJ3Ud_wd26b)iYle>J2*2v^{ak5IMuXIvCs21 z=}$L?T5C5}#>KPKK8?lWdJ1+g_~nWotGWQTUOH5{J^AN#MEEwenf`iXU1~QLUwXhe zyG8{vW4fH*c|E!S+ZKVh#pl=ZYaE^9eCJ5-HN^3Y#cM5uf?c$A@$%pWkm*r!3fvw{ z&NF5tDH3~L`)C2=z1Hb&wEN9PY$jClnYWh zH>^0iqzNXevDavW$r)}sIXVxSTO=A@KAk+ifKLx5r$FdIiq9S~vyRR^b}BA=mXL8F74t~>>!&v5(H zkCRgvm~B`eR=?TLFRj$=k8=&2HFkEJYp*I3CEIpB*;p>t%GudYzI3Gg+bWk|F2zR; zuA-LTYcB2JZ|LsE4!54ItUoedd(z!Cwu*18IqF(tt9WniQL$L(VwB%0Z8g@q<$K?4 zMGym+FQC-bvKbRunFX}bi-HH6nT0Y8;N;~<+AHs(ZvPS#y z#&)$e`b2GZGToi;Z*1}#wY_`t+78`kXP&FM;o}1S{pZy!wb(6fbe4g~-QTeGw+q|@ zkT2)oUEL{swXn8YE7tB-8`)3)uu@#gjzO-l>}5dn(XSPM7}uNaw!O8Wcxia%1s{m-+SOlR_lLeBfNI+UH%Wa z@mjeR>=(uN)|NVJQnyTs&Mka(ZVmV=~ zl&vV6K(he0uxeQ%yENYg(;BZK{Uye+73@Q22!oWm`cEMm+(RMWY3d;y1i|rdM8yPb705Bnt6-fb_ zX+T+&Xc0tJ1*SZVnkoviAuEb(Xa?(FQ6%bjRn`^5)O1=$ z)afZfpe>rFW&+xx4rx;+^#qV*O#^~y&`SWF3hF--i30VCfh~if!z|8Hr%Q;z#ca@Y zdqrIifyIJG>8fHgpwStJkP%RIOT#8M=&Df|qu5OEA?R#bKtz`fU4O{LHp^&}=4+)* zYr2Rvk)?%I6~uI@uxV&EPN!6W%pdd$!=M{FO{S9yEkGSEAVa5hAvR3v7Cm*Sp-TX0 zhQxqp=-B;Q6GCh~>Wzp``pELV z9uv3?1BX69mkHZKC%^%ULXXfY!;m-+Z7+6w+YMsRM*(mpq5IXiU)px9OwoX8TUxfwx+g6 zERWzl&-c~7Pc(dDXn0}r|p86Ds~I=GM=#+X=rGL8e!bMISmPeC!=ddGbLg+O}0DJId#ipeDK$sX;A zxLBg5ll$~)g6Qx^y|JykV}kZPU=A(f0Ybc?YiaZx3M`+gCP6F4r;J?M03h~&A<1g& zm^hBf03{RGqwf!BL})+q0w=~+;NiWYmzaSS(~jMc?)Za&Ya=D;^~a%){hk#P*>qiE zW9ra;fR$0ta9lzRYMf7f<%I(hI&{`hK*ng`6VE5qA$?ajjf08P_ktc7Da0fw3_KWwYGEy^ww=(T|hJN9G`)9_WcNa1KDCcm{GE;(C!03?s+7l#cqL^3lgn ze^2~kh;?|05BB=-XFwWn#T~=NHb1ZY%sGRkmxQpM!?IR?Q8Vc}3hUjj@?^1wFJMvq z%7yS}OSSv|n-Y8z3_kDic8aih9qzsE0Q2I$z-y!k$}{RRe>`UtWWGITS&|dA-R|=3DIGTTR##;t;v^*zcjspuVzt>iY^gKGA#R?L zh{s|(X}8C1e)jW$8GliJQGQfClV!Zk}JZPK(i3`x8qB9oq#R20wX8bbx@MWa5 zauuAs4pqvR$K~5=+*gikK!R2!(TEALt0p`9a+SzI2#oFnoxcUW+{K^#E#I|qd?7q^lab{DRN=Cby zgYC4h6x_Z7+a4V(;DOf=-GigWcEr^cyrx`s9i+U1i(VS?c_mrQ27S9B zFVIxG&T+m9(;wXc*^^7-ZjFJz)!c(~M)m2d$%SW=g)5GjvizkT*C*x0^ymp|Et#AO z@m)as2S=y<9vvK996Y#Wp&y*V|H&n7{8rO%MUf}xAoRuAQ*`>A_I;y)qnFUL&+m?0 z+>f|%r)04#isRi%*gn4nkeoU#xmMxejNQyOr>%cc*shkURnA`7Tgo+Lxm3YB_PuX$ zC-Um}-un-$8+Wz~Thq+=&1Cr2&a+o4eJ;a$Yp+7J{^jzHvD01StJUSN*&Dr9%jod? z+VMfDS$&OT*~^4yYm=R=4W6quKhd{prCf7KSHAj$Yb^oY`+l z`$BbVxA3f9S+4PSca$t?Fv2QfwBt3Wbe4Cm6-bMnNyG)=H%UQ?uiZ zBH!U*wOFrY3)N<8vsv3xb8qCUxqI?TKC_z5m-DaRX|Hs1OPNCPx2^U{rCnMt=Ie#p z-Q6BnQN$&)TdbFB-PUlKzsGGg^NqK+HeUPhe=>nfcZzL}Gg{m_x1VWd-!fOSU(atH zwyVv0CUew#yY4oMznKeH?j7tlm$z$c+xg<_?OLty{Vc~zd@;Aw&foiXF3x6ZYZwl? z+)~wjF6l@2p8aZ2t^MZa!`h$d8@WcS(Rt_n$ppXi)#B^ZLbJTy`Z2d!C~s#&A>RC_ zzxAq9bpJ6Y-Mv$8Y-DPc(mS=g+0uTcpXG{=vrj&Ge*Ecgs~!A&V%ug#@*#gHER|}cV(g!PpLS}U*Q{CfNi)*Fg(r%`>6DlF zrAa;;a|xGU<}&y0cL(|2M(0pz{QY7h^B=`Ebnl)Evza#zYYmgD=$X|_w@|KU%WK8K zO1zqTy_a9P>uqzgURddd?GJOU8n?8WD{^(Ns2yt?m15hOSn8Jg-Q2&)u0BZC%au3t zT*kOxtN-O*jse<8XF#=y*>?bjSQDY8=~w`UXh3KPqKJ@YXo`t+g@Kv2h;)|j4Oy0< zG77PUpeRb15sFnPD26IvEU@@_ET2Nm4Ew~GB}xNKHcv1$1fk3n4j8VDY%~3`hYZw2 zm`URs3?+s(ll4=v$n*kj4X4TAQgs1Sz;qK}z*GLTqcKSVpkZndpqA^1O6~d_mB6R}2m{GVHz@JL%*@6u$$u{YAGW8N>gTn|QBq}D8A`}!&F=ScP zfovdpiczf*bu@xNWhgGjP*h=>>`ui1h?=PaXu>o6Jbh$9y#`Ebu?{3rVMz-FS=9|w zr#%Rwq-m<4>4qrFnxIO8p)(?}VF*A1K-MHx02-jjB}LPaPUli*v~&r{Y-pO9$^e=y z7rTvQF-;nu%JVb+8AO_@m{>(D^-U_EfCP)qyoq&-RxnLqI3mky4-E}ShNdE@%7y_& zwnTKsP8S$`-7ri|&@2YzvwH#T{sA@wiB?xrO$OGriDV`?X<1J+DW6 zKPDK3HgWq#j}T()4Z+wqaDeQ<2%XsXBFhf~ll40uKyL_Xr6_PQnudfp6OxPw9NG6r zq=$#dMZ|JRY{5wD4?F-c34CMEvT-~ykSkGFMZgIWiX)GX#80f)4PqCBz7^TAMNDFN zR^*aHYZyDGqa=X#7GXkA7>9P?B99FF-q0F(Byc^{^P@O`!(Pvd#+VVO`vC~zz-7W6 zK|mBEc1_pp*%k?=9`?PF?_v`9ao-^$mu2*um@aW40F!`(#KAq{`ScA$-~*Wsa_Emh zK$tiKv0}$jhp*y6|NhucNH5ewHX8#o8IF=+K*qo)d(?Lx8Ids#yto(jt&rt!q*hsE zVG~&wC4r1zl?DVloTpL818<;2&YjMKk(3)uA#ssb~5NQwF@$cop5MIo)^*2 zu>QVd&_$Nw-w9CTfun0f%k-T-91t>%l1YEhMfLzWemG*oF+6ujh-PWyen`iu_X$ai z;mGQ_zUgWXap+PQ5)Ts#hq1dy=nN3x;^CNjH75Ni42Z2bgdD(u?L(W6P#lI1{p1S! zJqdcL(`AWRQUn6`A_oF5c2MlPei#Ojwqg=skpZ?0M<-rjn-S7O zjD7k(awBU9N1#V+H+DlWc9D7xV*jcB(Z^5!z4Eyr_6rHG;SDMNGYHXLOx=E=BXQb} zbA=6k33R4O@1(21HaiwwY5B4+R`4x)jHmdzeDg$)HIW_%(SlivO`!gZ;rSGq{o*1K zH}G0`Io20q-SCD*x0at>sDc`87vwYeGbgrzsbQrE!Pn4 z%Qf}_Dz%JbfjPmm4IjGBYCn`1j0W#TW7IV}khkZ5jN0)*%Rn`1|zzH3G`dqQG&2 zAGxU$xcJR?+}L&_$G2T4jr||FZj$)KLYObbmAII8vkoWCGJeMMe7BR&m-E$fDhR@y zpDkAWH0Q)@zRLJ%wp3QDOj^tYsODx+-{qE59-6N>f#;`FewEELft#+T`GV)B)8%}* z6y~eha=Dz%vn-dEvn5ncXUYuTmbhXzla^CyCU)oC3i^mEUQu!wlFOESE@i;R3Wn!a zf+C31IXB~`%UoD2c&WQmGI1s@L}98-d4X3lo)@N~AS{(-C+B7v$1k(_va`&xHzbzSvFk=!1oIHUdK)Ho2K1 z0?P`&SSYK7)a}eOWhE)lYXy1{^M!ypSb%&|M_4XEfjOUX;!;?OLKo=et9&+JKx1w( z<#{pdfe~OOUrn=o1^QZH<$(H?#Yz!# zfy<{#_VaJbH|3l1|B&)4H(&nvx6;`AO(!6J{MDBp6wULL!N8NfqL{_2>M83}Pt&~* zi@NT%K329adY-O4(f+n5rczM59ZK2sfup|W$%9S1!QJTIU^9$7P!vsuirdb($9h0` z?{Aotp`)R#N9e<=stjZW2rCA#i3gWGxo`A6Nl`sbR%L0>AHab&kotW*0I;ISFzBG* zqIi*SIacpw+;IP70m9xuzHeaY51N~IirW-@O;z`db^XA5rfBOIsF&bPF8XYU>2O(H z^Q=j#-j(%%?#XZk6IC_U8>kOyX~uom^_x;KDL-s?+dwTE8-)UZ19i>gz>teteITpY zZ{*uQXo%U|5?me_8?g+@Q)PKA&Bm7ZI#F(4pYl2=)|vz;VBJaCSVZ0G{ZLR9Mj5OX zbMLbQK-;jYZmIm?Fu;ki_7-^nBsW&P)q=8SO)co?1MDNp zorrg)A%6TfzWf|Y_W9@UZ*D$+|9MevZeQ2$aI`ttF7I#uiU!%%MWFUn`%R0R_c!-r z;J5diu9$%h#jVjle}B)%&6>-*aW@R#Y%z%saF?4~D(~OF#~nY%Z|h2Y2*bU{e+9|+ z1?l(elY+<3-)ETi^_sKyx3X>Cw{`HOkof0jOUm~fVb}Wk{IP;=KF`(_+4}4`!k^#V z)#I1!zRxY$jocu|_4^DAar1tC<^B6?OS`vR-Q0Iwzpc&jguUTPcFQ7e0km$7d~-Vh z5G%;vY^Y)WHbz|Q?dImrZkVr|b;CQJvWExnKTy)P3N|{t+0s__kj%EAx7=*2zVLzD z`s{wNn|mE?jCWJ8o^8j)ldM74?B>=ug{*hs^nTOt^Nq*f+!SPPw)(CM@zX!dukpv1 z_oZs*HwJsk^xOM?R)0fv_BrmPay_W(mA}o_zQ>o2HM7-{>%Uy1kD8@YyT&r3@>$#e zmOv1l0r93xe!))v;a|a-Ym;S2RtaomXO22jV_r73vK9~1?`s@G9&PkV}nYPxbbw2+K>R0+d zFQ1(AvhiEW!OwQY${XXR+GT$?`;*gJg&_{4f=H6;&viB3#z3hkH$e>5=CGMG;hG>NS3cXr@QiH)AQgCVr-{E!X^#KHNQ$>;0?4 z@1L=)Z@#e_UYyt8 zRDSyB`frMAX>j&yjqa}du2o{0?})q9={5UVGl{tF9?c&#>4C6E($xmpCJDX;#-JM% zc}$Tk;~z8_k|Bsg{(xZG1aYb>J9`96)kv@)T&F#?mNR2hiBOTx3upjG>2s&Pj{8>9Gli&Xj&ds9|%N-3#>A(8V!dg3J*(&p%|2sRVMRG0jq?PKs+?cdm zwQ4P`99K`7Yp>j@4Sw=-VZXU=e4%>fq;gXAHPY`8jBsJrMK0ub56=IzR(*HVO#b=3 zD)Gakvi1+SAHQqab)IGSm{@qTL-6h2IhP6Ukf_o0AC;N?&nq34IQ%Ig(yU$Cy}s6d zKp8Yim4EuxmzM3S{hq2CrfgY`<~jr2hFh>BJD%;}d%a`Jj$;iRSM^l0=en-%xt@!g zd#(aUj;qLxv24SE%NB0rx<(HM(rw#N9LIEenl0P5-m`$TYdS9I*2m5^&K2KWz{2qXaRUC?{+d6t{!CDpY5_@Gcd*%X1vdpV>AGb@NPt^G z6IPw{A2%*^bqpP7aLXL%!*szf?@**c02IhF;BRjWHXcz%< zkP(`mb>Rl1Ad3SR4XsH$xg5r3f((=((+!iMdL1X8VWG$ytI221r4b^KVlwi5OEG>a zj1Z6+`zT2gctIoNIm1h5yl%ngzjRSa35WEaS7-<~Dql?Ik)p3LZ zABaR&4554BMbjjlM4BUGCK0lO5bCA~jpP2<;}TcASf=Ay_!^!%N2>WzNOON3)R&ToyczjPOFs;&+(c^lI$5 zpuriuL>F0KiBM>vVSH&{<)6KM7kvw)MTzCSy}IyFcn#`DSu&nr{o5#wGf)*s=UO4S z#tmGYj`a)e%0^dy;DepP=N%2di_1lKt^lUyjZ3UGc`_bo^{dlb5Rd(d~izVV(K#G`(vxyu0R%$MNHC{`0)t z(s^YWd~l`z=zRF#4096T@vY)CxNl*@&!fgrjAzEha&Oc!9&KH`>zEX8Vex8xAdmHk z)?INvRMveNK6Cs+xwDz`xJG?&7Ch3qUcAauA2X-{K22{2w-Z$Jx{)qqZ z5v9?+dLI{kbKs0`l{YMUKW(ew+UPHPT=MYrZfN`29>H@JZV_zbFxql^%p~#8{p@?! zrQiOW*YqEK^%M2izqr)N55G`@m)Cxw=B8fsBX|u0VxCLNe7Vf{SN&V~?muC=r^$E! zn%Wfn89iHnJjTrI#ua6E_f5OXNwZBxt&t<1Yed3qe|}=E5}R zrd+<7=VB&6qs45#fJ!bCbFq_)%X!Xsc>#u*t-76jG0*0_xZoB-&aIT0xLnP;of*d~ zO4jM-)2SfL@K=gmK3jFg#cZ`$c11}LyPTlpVs{D52x`6zFN*!t68q(f(YD!bn~SI2ciNEbF8Q(&q>|cvNMNMtA!vgrKP|ri{)Y|thzH{w&EmSTrQL;hsWvw!43!} z<%`Y=xP~#ObFjk<*n7p3O5Un@PN|0Fy44%5;@?I-(@5^3^O8gn2%juXy}T=qjHsyE!k;mJ4adf$&l; z}C~6u)pwamGRQoX^31GC`U1*!~Or zO|H@f!DrHHrARr*1}0ib(y9yfa8csHwFG6hz-pZG8H_E$;KEYmf!-9fz3OyS*v(;2wO+j7|ZI*)u zzy>^cj5ve8Y$eR5t8A_;pi1eAvo3ZYB?p5;Xmp|N3}hEYDVuhLt{{OQ&Ov-(HJw8^ zWHbJ6|J8jj_D%Vwd{e$D-;{64|7XfmPxZIob!+%5>ASDX)nbCfp!g++-XZF=}icKyjAp6&8{Tlu4OHsv9U4|_eS zjTg(~Q6J9#kc&Ah-tB~s$K|=XBG1kt`LKafC`GbS!%fm?jsAIlN@%ire zg1=76ucziu9PD9-`##UyZ5|R`H@Ztj&yT1)ar7bam&@J1yf)KuK7arD_1%1w_joqa z%}p_b<>r1W(RSII-;-qz4zC|gYI)T8iTOq^P2&1s{>$V3*`vDb`MFY0k$7Sb&)vY! z*FDd|mi!OvUQ6sF0%y0A#6FzZ^;F-FUEe0V-SpY^*G1j+TFSfmO%LhZ&$rvEeBeb7 zRdm~IGiB_-EUoP3z8cSy%kHP>Ju$pNj)phvlWl& zJ!{PDgOP8xiQdnOd~w8&I(GJ|Rxfpa#K+gC^g($&>Fk5k?8)j^P<%F{K3!f8;^(`+ ze?^;5V&rw@lgYf_7V#O~JiNR?cD)GlxjbyA0D*{>Nte{B@+5U zQ$b{pk=W^nrb26;l2n9^>$o^#Cuf}?~+rD2y# zL~G|)D|CtC_87KYA2hqW6vga`D&L&!93PfX$$Gm?Kno8B(JL zcDdFdT1~D-mk%5D8uQD0%}(jB(>wo8p^JT9YBpM(&i*;k<_YGE5{NQeDOXx_UDzi} zL~Z|o5XcJAB1%lHLI`j6_RbE|YAf9jE9_3YL{}Q^XqW72bd&C|or68AUJ{t^Q{kKP zA)OIizW0YCvVBT0M+{XBIy6h|24z;*`2k(-)M{tcK2xfmRrMRc4q{enRGDRu-n2+C zV2P?%_seajS|bm7ryN%)6Q|$uOKjY#(3Sm~!*ML#tk-JnWxZi{81|g3SDo$=_2XL7 z{S%syY`^Z)jVXKRd`TT}6npb#SNYM|oAPg$nxwc>E?d}qhvyZg+z?L6EK^~cY|eJX ze|^-hQH***oVCx1%4ZDGskQe6x_SyMby%8kO9Y-7O5m>*acTEYxXRnhw^sLugz^4t z_)orQ*wvHjx4u^`mxk0C@3&ayi_#mS-fHYP?`4jt?vdSQy4T;K+HWY1AZl%f*k#)k z2|oPWmE#^karO4uIYX2i)xANP^vQaK*r_m8f~DwIg{W6RJ3Ce8oHziFCP7zarr*$x zXtG)<5sd?lA*sDet9$_3Btr6weRjW6IxLfvNRzvzN~u9p1jA5A`%Fu3iEXA2<5emo z1EEHCDjs!8SIdnCT{&rK;6hb6+5c-BW_7fCKIymx+3{ z*)R`I8M;}fex1`;yFu*A_1z;1JWrr&^&0z@Aj&7DgBHYXxmjm8>ZnYXce(^8kYGo; z(rVGP!9q6B&)=u(5N07pEx zcd|!tOr6|)gHHAuY;&i@Q%(M$!|YbiQ%EmV^^7W4%I#jQ)acS=ojo8lrc%p^dR^Nc zwAhJ3LW*Kr990qP$5M%carT<~$1Dig;C3qn&9K#0i5l!xI~wKIFROcWhv-pxpiP#m&6Y#bRpzX@ zce*3&G`N6#Q)XaPg{;zS`IINiOl`MT+BX_ni=y@qiSuTuU#$C&{tAN^f zs#TpjYxR4CLa+?M#wAYRYYn`ZX$bifmDPY@=FZ8zq+Q?So8gTT}^>p|CP&l3^=VuFR4wM^P<$ROjmiQ3C5$ zN>sVNQ@*G-OH{R7-s?hObJXquT|R+O?{vV)2%)rh-l{N%R1H!DI6-}9k7&{5CQ&0R zjZ&E<&PxrlObY~6qoH0Rs5g6NlVsaOqXc&cr9w2?wWAVCdo89V5gnS=Agdly6|!7r zI!E1_OjFGZiau*s&QD8Ky4pA^Q+p+-t&%KRW2s85!n5FrED5#x9!t<{t5&Kvl@ilt zODxbl;U6M;}0)k4w+99X$2euq@rtJl&OC z!*@*&F1VhiLs!c-9bnb%y9x{lhn{Z~vzI-?GkTVb|05s)C(ui^dw$RNEf>py5pRxT z^o+i34Q$05xC6@sDIAc(H~k(k0JK!B54qp>RMWLR$CMnP1q6U2(}Z@QO1oF+#dkCv zG}hBqukTrgV!<)+1B2p;vWkP}RNGiuO9LfJ_#f%EFBLj9@hdQ`K(z^ixlrw6nx@xx zEl@-snD#xb2b>jLDOf(>xreRexC3Zw`Tn4g3uv0Y20}QhuJrp>&*{r5=%{b$n&tFt z9SjY8fI&bnx~aH@u3X84t~RjYV;$m)7_Wy7r-QtnYlCTg=;S*lo`0Xs?@47n$}j^j$2r}k`c7(7F~=O|{+#lw0U9um(32X(@D zri8@+kqtb37*8PXX^!WES)74id^1sq?<*FbWe#>%U0XGL$HLxe^s&|)pank?o?Q(? zVUKk!O#}7zJus^Wz2Ha19)ah9yAB>6*nnYs;N*CgI@UfozdrzNcs;{*9jS+X)B+RP zp6+;#Vu0B-JlS2*aFpO54_g5v3pBL|BM*iJFH|s778XUqwZOh+S$)&)^&Ak|)@(SI z3^0ymLBPW3wu3cXsM&?!a(k)?5v7_?2R(3*f&%R#K=G_{Jb@oi$cBIdCSV{Fd`-ty zx?=SPeGpQ!eAP7vU`N}7j4&v`kyu8M-7fxHsjj12(p(dos@O=ttl{7o_ps~wt|nQI zVfz;R>DYNdRu~yWBuv`|J~TX~zvpPKi(L$ZAh5x3+5khDjt*9Yv;g+ev3vC}RMf}j z^B~ex_x4|=1)xInAR~aQ;nzoU<#0-d<`24@(`F^!`Z@8HOYl=QkvhyN>#-PHG0#n%fr1!I8qBpkFh zJNhD2cICEOAG0lT;5VpqfLKrk5?jZkC|$T5&@EgLc|gpS_>XVh%hP<5-| z9A{et!yCXs2d0f}3R*V`-MFf17ip-tlR!h=!XtumaK83%R#7!@BS}`lL&3OUL!59u zzuyOy_=e%iCRoJ4&>9@yh54~RLFNZ-^mObSMQVf>#lSIwvj<3ty+QY-LT-o@Jd@C~ zhtVY(Ogs;vSWj$K_U(S!SKP!5qe(Id`=KR!R)CDrSg~znIk6XBI7xUFCf8_ep$J_m zL7)vUz$sDBb|ouxWJw<=PMmiW-wMXDu1A6442LL+kq1h%>|v^D4&)?GZv&dV#D2p;0_lkbQ|<+d_#x%mR=JxmS4*qi{3{#sf!9 zY?LbCHG!T4X{ud7gVan%LnHE$!P=gJ_@1;g~`N%P7zX3d}W3Xu;-w_ zOCr|~mDmkc1Ps{rbn0J+c4Rn`>l^V1`EioODN2&!8Nfpcf-&C)K@y;`uYs&^#fgv) zKQ{7I+fcOFNkhZ7M;GzfOpzVL1B8$p=xz`=$xuc9I3K6hSTnWZc#^un(&aFDqhvaY0yF`hT|d=OmKm`bBioG=KS$a)azQgm zI84U=H40I5F$RUj{zW=LzL5oS8iY2U(+`ex1u+bn0gM`YQJN3aVKlNPku!AiQ92#v z9$3|h{ZzhiqSzV1W7yOTZ7=rxxT_5MD9Cg*z46l=JQpl)havPG#TO&@YBbDaG_Vo6 z2)q!injqgp;B1PAE{qfn965+X$5!G9Zo!U+)c69}46pPk0&jA{P?gglK(TFw8PWn2 zSn#w3_lp2INjx!3PnY8>Gzx9FZltmfE*_+ilr9m{y%=4%agYw7*L50SJBdF=2rLje zZ!LEOy13K=NH*i)l|9r$AOaS5LBkg)#E(CIFp_)?P2y;XlJwd@$niqgj*uC3jd^SL-ktRwCeAq}GV$jH2 z2q`B}Kx#Af2B|)V2aXs&0va>TH+_0SCzeiKlW40 z9e9y_1>OLsDK+K5;UKM!51QdYu$!(>|a?#fxB#An8-245a_X~rH=d# zseTV`CU!cBY#F(Ok(Rh-0OTzQx6pL1Py`=EO#(>E+Oik|EYsI1WR&F9bQL zC5)17eWrrkT*$&@CgX+!N^Z8 zMxh7Ml8z0?*gZXR!w~K`qr|lEbDZuZUOaTc#URNAkRz=aWQ(WqIQ0`3jm@j!W$5H8 zN=E58xNvZEPOZ=#^#k}g7Dg!0QR)mWxU~kufjmhNeERcI6u{H59C@Qjamz`k38c`( zf#>r9q_Aty!1&6sBsAGfv$xA%{qZ%inPvaofBS#G`k(*KA6@z1`5&%+_22k!uZmgr z3Z7cuhhH0m6I={*NDG+4u$X`!uTde=9n2%#AR}UDSj^AI$OsH?(DC75oQ#q?#D~5$ zd;bBRBHiF3?kk7mIQH*g6q-IR&g>23Lc#~5HE6@%0?Vigj56FHS&ZjL-wwW)|j1JOvtE!qF5lzP#=vSlr$YEV{>@Vy=H7s3Zrr0Vws2jFj>nN z73$dnhS+y<+rEiajBy|ueoY?YrlhsPk^(Sdx>!E}jALQBG<+@Ia4_6R92xl7dIWk= z?~p6Qt#^5IG4jR_>f@n;`Ayae-=L}7{-*b+a2NxRIob@oHnVn1=8p6Rev>2x+^NuG ze5cKOu+OHW`w$nVkDcN~(ryO^rV?m`DFj}jQ{cTXZ3O6#M@FGu6LWr6glHxZ~1F3K4Jn!^7W(%-A2UJ>=fPK3s6e z39glIy?->0H<&DC!^>9D{10$~#yE)9m*7F5csGKr?zgf8+lJf-zvg9FIQ=?iB3ua` zw#DAK$XbBNzDH~&clCF}03(4qegf5%Y#2yx4Yna0-=%wTH z@vR!y^x^Zu9egf%jAq0Y!_hdx5@B6ELP_2N0P%|(VDAGoz`3}|trE5{-B6`Mmw)FA%Mxl&?^zHRqzjEzj=mfWLALNtu zIFdWwh7YF3{aK-(=wXjy;5*9}XPe|}6sqtFCG~F`eF*bQA8IgI3$1Mci{@I-wyEB# z+OgLoSleFcZH2<1|Ml`7 zZYJGA(EhOUS_qm8AJ2XiIDSgZ=N(DGKrK<3<258DVY*x_q~((1Ik+rNr_1T8(^+;T zamw-8v@@GcCBDN;os6F^=8`xUl&RF=I!logI?95}I7w8*jGJ@ajPG&_5eO}oof*e< zp*Ek3ov9)M{iz^G%X~i1`QVI=}+I>SP_B<7W~t@yd#mmXg9LOKB#~ zc_kNS`7GmC;&QoK&8D5DB1vKf94@)3(9Hy10T~o&J_S~?r7)fIT$h(5E|Y{ACvcLG z3HdY=rmID#yA)UXTv&k2)1{(xd49RfI$So-I}4Bli^yfX2qH)v9KbLc4+pp+%Xto1 z%;sEY&aI$Yk-966?*i*f0dxwg<0Yt^b}{q}Wa)5{q;$mPe6g72Q!Zb0W=g)`K@a(~ zBh0(g4kzSG2}TCRtpsk#N!)w|Cg8hWVJYDiLs!cwlo|YST&D}l#f6uqoX}n5(n^{y z@|gs~^Ib)ng1PWn#w{{|%S2$QBXpOUB4i+?$WIk6=lOXDFD$BvpePUl;}MtBZVpXW ziU<}HS6#j%)X+a-g>BIsnwi`kMBX8a;w&Nyj?yGpAJbddowAVwz_7dhx}wgA-%I^$PUNl^BimqTET$JnYaQqK}U>M6#3P% z%Rv;*AS#5;G>7X7cu8m85ti9XoXt8s_+AdC$rj*AHepWYO`5I_-P#C%lN~m#+L6cEB6!zPm)qT4&1sg z9|z6-!sTm_mY+ECUWH$J4)XH}m?iagq2^~+rhZViH2vWS&o3N)-@Ql2<-aT7SGCg>{YF)O#%=hgd zRsG*kp6BqX@cRWYiVu?DYZ1%O7mSd7jZ43t+>_;H0PWWR*A|05tA@cn=?_%>NrMia zZa;Y0gz^Uiy$baCsxbQ`r+(>n`JjA6pueoLS(5)@QC>Cp!+y#KOOt)ga`O~^=F#DY zaF|yB)Sko8d<=N_0`}%vR=3J6W-xoE!OO^=XMluvh}dF)=gGewANu)U8m8*0@=kc6mn5zwGkpl^!mit`Q>s*Acl6V%L~s-{-kEZq=@N{gm}l}7m=9ZE#` zjA+xR$J78=rCH{meKU;@YfZYwR1VIF`c;`|ku>wBO6^f6T#bMcWTIUrs1{$ZkQKU5 z?9}&;Y6R0DPW)13XaBU;6iQ63^@eiFXT360C9CB&U82e6E<+OysoEvU1~Z`AysVX~ zMDvZbOOyr^X?8?&wVSFjW`q)XST5JwK3|(=2XBNH!8VBwP$23=yYqWHwU$aX8y%KW zj!$Ydeae(73`d{7-D8ACk2#~;ZMs5`Wk&2&GlnAe*z=td^&6#qhCC(8N#jk8riey6 z=9w15(z`@+w@P*i_LQu0b$XYn?v#(JM46x~_2Yv|^^|~7f2$07ZTDLz%<(n-#dqq= z!4YLJdl>zDa?+#8eHKQn)fn-h%5-+mcBxv0Jg75`QvGkxE@5bI?UF(g%_dVJc8Ju;E5^}npKoi?{~UZE>L<#$MopCzh0Lakb>GeYx>q?k5A^@;KuxUesm&&otYe8Vvz zS)nTXv`DfPK@n$E{fjH9RBd_3Rf^;(vT;nXLmTEUmTW8VywO!owq8d zO_w2eY6Mwh$+NiHEnifblF3&OkDLlw{^@0{#hv_bwJLeR1SCgUXVSO#``6$pd*|&p z^{M#Rf?bcS9?)EcX$z#q?$I=>*7g_@;-Q_;-IMwu$#mMamULJt6W~HEu0in!RB5MF z=@4bIS#DAttMbk%d33e8-)NTzgJ9}y=K72vDrXh?&lm>eu7Z*(T#0K`+syBu)Ib&c z?MiK*D(|()v(gS&l-dgzf+&@^8p$`n)83O6;!TSa_>(qU5|4ShR^8t}sQfZ`9?@@?8q*eeRhf0#J2Y)FP3FuY&dF-+vr?OA za+QN0|3{>gpzDk55RtMsvqR zt-{dEIZ4v>a=qGUsx(g@C0&XRo$g+R-a9yE)yCm2as)8Q{4P=9_I0|!G|JV_ zt~wCp=evYSm8nyrvUgamLl$katTXyRtd$i;1?F-dr zf4|xxf2}mwCy4!@(0t|is7lr#4+(T#J*v6Qdi!$sqRT<5E(IFZlFP&{*wA#B>OZW(1^T$nG0}dv13^ZBT6#^YQIAUHa`SutdHYc0S_Y&6 znmw(RA#N%H*Q!%sk;d*Z`*-yE_gR5CD^XRp=I&m1#1eI=UN@;dmZ3@wVc*sEy*hYV zbszgQvD<+RN;1^}-cSqdaS}AItJF?^hpZEH>9j%7#D0~iLMpA4>-ACNyfUlQnvAe_ zPX8%E2_(ywS@O6+9M<8n0TSVNOC(;y;Do65cXs=9lis6yY^% zQCwx|ccprTFR?%U>PrJhK3onVw-6I~GD44DG@w zUER`*f#!IoVq0qrrU92-+p|q*RlxNM6tM4F@M_-f2kQF;iqjwT92Wy6?E=1qZnZVoOj`q5eaW|!K6G&n$J1TA zKolCTi*dvSy3;o`v)I!K13`gN$#Znm^$fGXu{xF|YsEf8#V$P-J~lAZuGi~%I`C^@ zW-LqB*8e3`v2;KIi{xPll;dka9&h3UvKhT%8>j;9W)yJaK1T9c7T)s4(TpBwW{sBi zFk%h3Gkgpb?Ypk(V6d9ytGZVpb_+0}?({H-(NPVcEfv@{3?lSxj2Q$epqcGyYe=AP zsD^6w4GfU=T@2gvHC0tzzlWiFuBRHdiV@q`1iGsjc$*=t2gi0j*}>Re4^#6TS8~>{ zTMVsJ!BnPRn9sx_Tkv9FD5++eD(-<1u{{;<2!sK%x@NeVA@#fhNQp6?j;#a31CXkR zw>knc0}Vs8L9L4Kn-~S_`?6_St~#(hjDa)@+#x8|@GQx*uqYaq6z`?!VGtqKfCL(J zOkhX#TuFBwjFHf7yxEpvuiebE4HazbVQeT?IF=85$5m}`Yp{cZLG5zkzOHLxt>f*G zzzE>qFs25kbHKaw0t9QwU_&2+Dgb*xguhM0v}{+wyH5=~a5ub(m!yH`sFo}bgGy1l+@Xm}qc+XeSh9oI4)85HTLmR`WEUBB<(xWZsm2mrNc3c?owU91GF^`O?$ zU5w_$8$4lnF@_EIasF^64@2cae@4&7@K+fa#J-3D_qJn#TR~`n`upH8Fx;Srzv1u| zP>F4+UauI}EPS~D+85AM2m5)!GB^UbiG-aLDvaV^zeSdEF(MuKfl$=&Dg}5O3Gg~q zF+EuWjp7Y|VF1g-3k`S}RE!YoOv{z{~~Xge@vP!yzB z3oG65q`q(Wu?PjS*2SywLh80d5mt>EjDvj$INWB0&mAb?#QB48MZV;gQ07~G4|rqplZ-aG;JCo+xB+F_ZW{p<5V)ZeobLj_;J<#a6NKz}idk zFOD2X!s*#Iie(xsyu1Y7WzWaUfT#-G-*EoZU917Ph5C5?1RQmEr2xMGpSdPTZ}xhc z26q_M!5#ynIRzFU-@;s+gz%lx#@51HEX!D-KnO#vmBcpUFwu}|TS*$G)*$Tr?qGNU z*)X{n4nKJc+#qv=oN3^r=<1y}c2p1PC?1Wy%MthkGJ_CVX)+2OMIIq-XqzrF zd_7UUVKUG_Tbgy@kK+;OM~zJjL13AQ(KjO}F#K?+pz+ww5HkG`^q3{q*zm?ifVWiB z(}8(8><{hhDAf^4uE4q|b>i4S_Q)KDmna^`o-y{O6Qm@U`lW*qzFEeh6Qm=Ih|Lo; z4u@7Apd@-1#S=71;vgBtW)vXb8_KaAUic%7`VB_Ip$WGP8~M?d?ZnB*N!>{tBG8wC zL9Wol3aCNI;SnDSzCD1%!8@?|TEOh5756!`Nlyf6$09&*fhG8#bw z#W3EkZ?hFQZ(@+(54+B&&2sNy+C>J7CE7d95i&o5u7943^7{N z4KBjb0KyAtdIYLUOg)+S=5XS~(FEe`5)@!_tgM(?IAHGF_6-NW#RuBq9*F}M+$Bt<^=vtFw?-J7+!4uNdg9wa9VGvAE zsJZb?jf547ioQH(R;*v*{q?Qmjxv3}8yKxiYdf}v|9 zPG%+eGghjChj_ur9*s=6C!|BX{sTNz1c@^?ohZ=_yzwN2CTICSVm%gBC#yn&UC@E=&tU-ywL0ZgLTLaSrzYJBfAo0=kdlM1Q$xjz9hpV6$H2) z;&o~)ZRn#=wTD+@6!c9<_5LL`778v0fdQX9Omk@211BEgy+0L*Vfcs#_fJ1T*O&e% z@!^hUK*k9mpG0E_~VH72oo*6(MRPod66l?$y>w%Z!kN=R$Qa^E`0i^ygHOx>?5=dPr z4r4VK!hpuagfMcZ;{dOUas`>rPmGbJUxco6l@3j#KZ%sL&UkR4j}TZ%w=9&5AunBr zv0{aKY^CW{IC*ROL(6oB7hzxy{gLViaK|=-G#FiNuQ|x-Ve$zg4M^P@le}B zTMqGYw1JtY8*HbKe}g+5p;c_XsEr>KeU0mTXF8DQ=jHcsx|N{1DX$(q}8ska`c0&V>kXl!HLdclTmVs7Kn=%rmO$6KuWKJ?W$ zJcS#93Vd@q9^S855EN2k1h{ppk;F@YJ$LOrPmH#4n{*rvH^UX4aO)~-n6cUHl^&`f`S_z{&9*prlg!~Tu-gj|JEP@@}4uce*zbc)3#OC=PZyj_PEQ^4f!0_WC4_4NV)YZ)TE;)%WHWg~wP&sgd9rv2Ku zcW8h57VXc)AEN#9S8q5QI7#rMFbzDSyIOYVGhx+TiTo;GV|;~0H_ztX)odwpt9+gb z7(l*S&G4SE3k;H$mdd<46{ney^Wwal30=H>=_=2KE{C^?6}p|dIGamTj^}xdPG08H zY?jR=MO+BQ&ZN*a6IQ&^$rstIE9CiV(Ou5FOKvI5=F{0~)y;WMRHohOe38w8*mAba zxy~w^VU+$-na+ev$jFmy1jg7qgBC;scebvY5^IVi#Png2;8|T}}{Yi|Kqd%a>gNZ|1w03B05TiZWks zgDU`McpuyaXkjWX#Z`9(Vu*s+0TVBPmsuz8EQFP~Tr9ze7~2hlt~b9GJ6XOIZa2T3 zD_PcA&exmYDmloX^FV64S}9sFS7&=6+V7$ve5Q%9l$pfV2|vF2($kUrOR;(_44}hw5O^{tVnm>SnVJ zUc6y0;SFyWs|*}#wFGY}JPPY~-dRd;GM`EUSiRWo7Wf5T7K$Pjo82yyyl}47awNIhw)~&nY7|~MN;r07Rqup>j0-yAOyj-Salb9 zr!!OLx!9cw9Z_7amebik9dO+@<(u+N`KEkRzA682FCPJl51!fe?_=dd^q=-3-t8p_ z+!n3DlThEMS(9I^eYUKd-(%h$LquN*?|cSq{%o7qae3EY{@}`!r(5MozMq5kDNi%? zmjOe3Jv>%^{_L?)p53AJ34N%~SG}@4+D>=7XfK{_$}fl$Ey`p4NiX&N`a8FNl9oQ= z#J|ASr+3o64ukus#RtBoer%J{`@w#(^0mR=&qUtGd)$_f>*&Qji`5TWe1b#|c8$ib z$`%3jbwYj6MtQ9=KH5rtUYIpnUHuyQO;*=``cu&7d;IdJ0cxLsM%`a}V%xx%0ApLU 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

01sDshtm56|G<&g5!C`W1i8s%qgB3`>A`DkHeH5 zQl*kg!6^9F0oLI@K?Cgq^oY5^-NT)n&3@6Mc%(h4F0WEy9NhXmF|hBU=#3)=l<`r@ zz*!a*M?e>Ft*R%4;b3%)Loh>B>2b#gGx8!hj?44_e4t-&+~`l<6?-4hJ7;H|dpPoG z_^m3*k-t1_HI^XIapoyhu6J(?YdkJdpoX? zC2Fnc!-w^Hctkb=(^h(kTo(81!Tol*+G^L=<#w>u_0{!uM>ev8mDhuHZ?i-Kj`gtI z_O6%O^#(~m`m15N91MG~(F(pjtk$Itmh|D}RxbzJ)kf1FwwoSqIfO}@hr#fE^H2`U z>-*kvd9xa9da%}dxY3ur)kC>m>ZMlR-)n>6^+WHzT!9VSVQ;nUFOhrW;o+gT8E6li zp1$2`<)F8QZ_Dd}zTRl-9(Z-r?`f;vptszt@0aVFm39NC9tlT~Z)C9DXoJ;eQ?7?7 zlrw;JAv}A&kv=%Lg+0NDhc)=HryGG#^@qdNpd4I7;2$cw5tw;@J>2U32W<&9-Y*B* z0CpJ;v|b-B96SvB+HgI%DersN>-GITxLcOnl|EdrwbkHZ1>W{yk>34E8={QQb_>>R zhihaS(X^W(5{;}%2>bFHVmG)RtT#8MHiTSkZ@`6RIb3PWif06N$7DUgwJ>=&Sb-0F znvoJh_WWti*}s&4dFI`djjI;E{>A#Ax4@ri%U!!KkwXIpB;UC zRc-UEub<@syZ$AzjnJ=zX&mN*!eljex|OBXC;lkb=5F}Py3c|sez_jbm&7Mek3POCzp~dC8zA@qO#dw+ z3rcuZ{tT|*k8R<91rYMf&@_jgzp8Wdt$oX9cK_Bz#{h^g^nsqPa=gp|@$-3jo-M5X z-=DLXlpjA;>F0o%-Kk#?u4ff0iB6lv-c-`%^ej@AR%4>hHu8u{P<6ud>ddo4)Qe&jq>B zdv~EW)rR|BLdDJKe6-uBmlFltiU@_GTah#dCe+%kTBG}eB#1*n zXk65~a_gTd>a8#R<}^9`{R>xUx5R6qH85MPlTJ-;2_3m;w?$Fxw9d3npNg+f>#BMp z)jNtUh%f)H)_m1co3E6s*H=p8g)hI%hiA=!crGci(q4Dvs|Ez2)>36rP|r`UB>C#a z`uo1vR0bVEmF4D%@>=ezZ~qpIZwQUE7md1TWRe;VgxBZ7TyCfkGP!Xz{pl}O+IdSo zshys`txKvTO7(_%s)?c?{gf$UTkNVYZ#v?+aB?!}$=%Z${u|7VYzeK?H?>->z3nSf zJwrHohDvwO8NOy27a-sVy0TtJdnWbfU;L>0GY8RL<(xq9UA%gI8Bq&Hl;1t##iv zWu>c}&)?QWTefUz(CtedO%^LYk#4swG`sCutJ!OGuNwbp7|H*p@unfE{aQm7>Tl$W z=1{EH-dvmum*2I9YNw~S740f&t8Z%cmUQ;=uB(cdy0C%%>8;YL zb%dHac(qhTMO7rrIGYTFvsS$$x7Eh~R$q(XDfNrHbNLKHp)^#XeGT<{*-_g!m)^84 zTuFnPd@d^Olcp{=oAvI+L!@@=^535#V@6FB#O7ZoFRuHdQu{Ar^FJthU1*-D=S`v2 zR6Fnf^P8SBd}r3By42{rlm^Ylh1d+?Ze-1yUbp=cd}?*hyMHfqx-aS%-=ApWE9qVl zq;9SA-9nbnWu-Z6D{nr&?jXWOu%-IDX5;ngK)L7!P5)dJ>mA`cMYzcuP#?~jI+S0^ zFaFQ}{J+;dL22mU|5&@K*Jbgw(2#z-QpB@&qh{}APl%d1m3ME{HdS8?FJ<|iEOol)Z9(eP zCoj5X=gd7lpY<=zmfyc<58ADIp#F;+sfN5DK9VVT1hECwMY0d<@Qz&K5qR%9m6i<3 zoM6-4bWx$jvxwoDjIt@i)-|MU*yl$E1N;%qcbShWHco|AV3qub&*;?Ky=N%>0_#$bB4GxSId~M+ zLXdj{cCjfopous395UWmnw@Mfnxa(Z)#G zf&3@P24P@d-z6r@Fp$gytaebG2HX3@tr##Su1_lx4yrMOj>%+1m}PpE1j>lHjz!@c zs@y=VEmSmdM?RR2S~CuW6V|aPqb4c(_TG;O4thG}__R}14sN64Dt_(aF}T6Cuz1U6ar z1Us|H)!^IiR5vZ+n$E;Twi0h_fdhtZBCCoIzoD9JWHJWUj3K}l=9^O6uH=0*=0d~` zM}uR?@_Dl3HMT~4la9bu8}0%& zatzbNlRAQAkTwKGk$l&I;K1t<+@i=-f;{T)>M);P?H{U9B{wFOrdW``@$UCpqfbylNl37b0Any zL{R+>K1J~NeC^^(cvo(EV71MM{d0FYPS$k~|2#NOyUZ!_AeKd^$1tERMaBg*G?6={UB?EM$d4 zT!V8n<+Be&Uj*EpGd|_H&)&~M?k>0!`)SNGKfB{APPof6H>F`P%OH_ya(jo*o^-J$ zi^M5Nkmm(Svz&V&i-YBlA@QOt@FUwTf*Frv=k~`Wf!nw=1207roeEe~ks&v+OoS>mSUnE5oWO>dxPa@xp9Ga7P!E-NW zy2n!z7-f*AUQBQNz|Kk*)3o5B$D%m7WvkR%xbX|T7k+j9)xkLOY$Wi3}n1KQDE$r$BF=3HGOvfm<@pVl(D^;=y~Wr4e5^GbFI!5q!8grsJ8K_nxxUM^Hw93^Z{X()2xq0SZ-57CcUw_hXO- z+;Acw zkzXVb`o#=|h^E=CIfJN1h?Wc^mW9qN9W58L8D~M@MlS42a+1>^w^I%eKj)6a9?2^7 z(=2d3SkdMSBY?-jp9N$-w|St=bCj*(emFDe$2n5Cz{e^D_dKMP@vUqbAD|;YT>kzK zKmD)Xx1l50k~Zi;Kcv|8ui=o#f&+;}h7J2i_6uxUvwch3E{$Bmss!1t;A6sAw5gn6zijXVav;#SG_ zQK@|TERhM`LHi`9)j2SWR;5Rd@8&OHCI1im{39ls>i_^BiwFb&00000{{{d;LjnLT zZS1|35&7^OG_X;G0y`K4 z&TqnK;8V*xVIeBTm9ku?=|YH=Sd`*e5ZalXB}rRai*j2? zt^fSmX@}Z-WyqVn)coI$!7*F?#iZvlKjYHdcJ@xiag7(syd>CrbIc0{Kh?CC z#(OTQ`mfCCCk?!3)PHvVtm$7#DIa@utbCm@zM`F2Yv+;Psi?he_#K3Oritd7 zx*vENGskDoeWJ-J231i@eeK1Sr&or&Ipt|bdj6d43lV;J{374&gy*Ww ze|UOH=>?1Vn`4gJPinOt^^(@JnNKeU{B=2fohUy%cg0J_^PiOE_1W{Ul;Ee^{I!#3 zMvUjX?$>0=Pv^%%9o%^;X8gu+KKE-v;9sR37{*UO#M`r{*JO!b>wJ^irhT>aFUg)x zeX$f?mE%R&JRe2<=|4yw$zSTlpO>#%75kF^~>|ZcNbix!j|4q6jiNPS-Qvxm^wX5sd-`M!8_&3&M21r{bXD<7F*tyGsU+3(J8u8JQgQt4ems53>DX^5o;RpME$ z(7!HJuh{?gl5I6=6{^W|P3e~c#dd3>0$UTWFZn`&7q0l9m(D9flPR;LgYOe|IG+rkx16}UQo-sFq*^K&3_eOW4f_ldgt!;f4^ zVPl}>Y>BY6$r7Abw+sb!c znit-i;)k>MB7_CSHS5)OixHSQUuiJxEmxrm1y&TO>-Oat1;X7Himb@;RHfQvs7mSL zvdFY5OogpBsS;N&Trt(A(PYj`7v+ognN+0;<;oTPp~ig2AVH~eT%8f?EFBe4qk1nF ztIdueP-hH%Q*8_1^J>K_-IQqNoT`UcX5*%K!z?)Vp;(}(a=Bb=*2@%Ix#o(!a;ZR9 zstntBPoEd44$HGrnWDJ=^I!Z`i!Q&XSPtTzrznYUD(qdgFlu}(SFbOMKEqL;!G?wR z*XOlDt6#LKGx|*6Dh2BURS^sHyGlhYR;haDg00FjrQa5r3U|ei>5#jupHO+ z9NV>A7kNF;(G1tqT?ZaWk!NejL&!x=UvoPqIdBz4?IXAAxGu~#kmn$HRI(IR)sd@O zw%M~R8|jYhm@4W!mgDG(qgjrIoDMvv8OZI~mSfne=V^{(BZQou;W$V|o@sVn*Vati zwJj5vDZl|_aZQjwaXJp__bt;fP0j5?k7`@+9EgwxI(R1ZfOPpcNMl;I*LOXTrfWD| zgbds1bz}wUHnJVt)IHZzU}RtMTZYdkOjT1HViN@(N;_aCWauypSOCwC?rJ&!VnCh0=ns|v z&49iKW+!xAmB;aG7SaEoxV!=5F?t%LGaxNiIC=)s4D}Hz6l!k zEzdTH6ATL&X`P;lG_4Dcg}-=p(*a^;$LZt>dA4WtUCs1NON9wtqNA%IVr3$y-9fh6 zbs^fwXs}veHIb>Pmg#6F=^(;dU{gc4VVH+3ICr}?1c*!A0e@zAASU_S9~e5W=>U5O zQ&7$}h;*)L+a#`CQ#Nc{1(uF$s0c{e;MqLfJ05u4(m^1k^ug!go4(QqOBmojaJ1rd zEfWG`BMdO~bchw84D*2icnH4X*z}O8L8ySydzNN^up~|(EWz?H*8&rg(cl%?1kPs8 zoPd+B7{&?YO4u=JX6=Oql3&b5&&$mqrgRdX{S$x!yKJ6Ua^d*^j>-hdxr=c%Wl< zteN9@?1r8*^-(+>%&<8P+^LPn&NOgF;dt<1I3Wt{5%#b>n0x6c=zI9#@qY5z2*cR6 zr~dt;?^}4}VpGRsGsgZvOJYYiG5#KpechN2G(5HK`w1RQW@tFV!|}xPhsMY;A3u#F zFU0N$JP?fTO+0%Xgu~&$9U89ofKfCu(7@@3$j3l8z!)PGK@8&P(ZM0cqv60%j=wa~X`4%P;-H+Z-oMOGAykZ*=TG=THj zeK@sEV>SyW)3Fm_6wI+P2*Qa!MA$LL1J9dI1`(Noogv1a7l7=a%zF&?PglWMA1S^c zMY=N?4TiCgeT*jq8|?6DiUZyIG=e!+{%r-GX(SVG7{<;l4BU}D!PY1mg!(iL!zlDE zXO6Hk`WcEQp=&*a2#p~ELb$KH7zg;lj~?9s^z$Yo&yKFpxGJ1oxw<<2&|f2K>hmmk&K`ImDhRi0auxCm6W%M=LUh4^tgG@P)gh0EdP- zHv8Ui^cezUlH4QkfjyZHL)=5YO-4n*FapQnk=YL(G`J7q2!$@#*Pjk??1rX|jY-#t z+`*(X!HOGVJ(yY}M4&`8!E*$+GCUgr zE9^Vw2m)z5!Q)^Yj>e;SU>Fd*5HltU#sg;a5Yb`XVASVVm^@F#u{%n*3nSG@pY>;Zc^4*co88!CgbZ450ugSCuf&5j~lzeo3j zM^hhp1Mq|c975m)E`%UT29x{HRYEs-h(_)>Tns&T5YEA~)6kpPvvJP}M;7i+jZrkj z2}tNYh9 z?@pZQFo5L&>o~Ho-i@#~0J+dGn2eopIP%9XEWpoJ7zViiNypRBb^JA5* z>*Imv55^(&_y55o{o|kf>R;Ua_~*a+4=?}x?nXXT$g{2%tmhd=tiX7SJe zhkrZ%^B;dbnJC^QZ`x$n2GB`9dy|PTPhK=w=98{|)M3N7N-pd=V73n*E;$}fyv^8f zqEAK>Gd~{NWUM^c@ae<1?jGm`J0g<-T@HeIL!!f+2@w?SPSC_XxsvPV$~h|t z{S66oPmRoQRdQl)Plub2(eAQNNc8i=4Q1zWMc$3Ft%-NAz%VBg9LeGDj>zN?4-%?H9m7&inSWpH`x3Q)4HV1i( zM8hL4TN4fP2_Q>n=ebQdf$Zq$40)4H0B+kZw(QAK$b?&h&cL3eKWrZ0vJTcjWKp3JYvR3-JT6{qa)(0fDj)a1fA?y=Suk+vA^mK zCfiYaJx)FBZ=}@o>$^2*Zn+OO*4WCkGjM-D8LX-v&US5M)J+_R+Ge)0HHNdlP9!xZ z=I*{>Z2EwOF_=*Q@t^(bs`y9$(Ifj0fBZWHZ}I!DU^4#Tt1%hj5IQ1w?4vSixe`;6 zpc#_&s+CBw61QU|S;tw{ZpCsdZYOD*fFDFzY%kaAmAGCelDJgv)^Y~ti6o11I}uir zD8+Jnm9?{_xLhacI%y~C_F}E1!g`&pk|ax&^+H?_tcKK<7fUH#x8qDmv(_Tc;&|B- zGZ{W4S0AY7VUT~C9AlVwS;A>og{bhA{OtUce&28 zyEI!TN}Nj4suj25B?z_mRYv`Pyc38wBOpd z_O1PE-<~5ewy9t3OX=I=)T;LC;b{i<&Grft_#T5Czy@Fr(0;D0Q_(~GFznP_N z=bq%HwHH%<5;O6#8E@pS-)icP^D}w+`F}_5Y3`cRdqKT-n16K501CvEKaryEZMc68 z66HvSpCFhs{sPHoD&!)n{oa21EA1KF=gR`VI_IsXJmX2E>28mWlinl7Cl@x?o+E&E z?X_t5vQzr5uJ6a}j`rq!jb8T%)3k4236@dGytf7FACc)lANUH+Cx>8c6Q*CxzdyZx zJb(4@OYM~u?w(#w;_-CMTSC3U?h6vcZ(NTzy-%+tzvnNe{51dyM^pYUI)I0~R`~+5FV~nrQ;OC-!Nx^vc;|qi4ubj>w_cPxl`xb#W+SmEv z=@r_KN5?1ppI%&;zYdv*j|aSHUzYzV$3Yx8o`%S4bDvJ4;DrcZZ1HYQydlgHnHPcb zV)<;b7vwK;k(L;iuGjzWpEb%AhOTiURbVO%R}~qSS5lrN#}*R$9zikz0xX=a~*w<8BLut3NE2`9^`Je_1S^S1ZNK(r?!;S^|4^RVy>) zvhFkN%}tA;uNkUTps131Q(=o&tk|V$JWwmr4X+ZE8r9OfvdNTmwye^%R>xthf> zZj@TWS*zAOFS3=ZhFEUfRH0@u6kVtmT3oSARWD7Jr5n6RS3fo`YJqsp^EX9aWZ!>I zs~5HZ{N`Ou--UOjLXqJ)z7)F)UgpK?dc9WaG|TsFv0R||?_8>Wb$63gM4ji$^P479 zJEJd~rSsB5ol*q;@~qUTH-rXtt5(`-p?1SGC@L!a&?uq@s?Jub6n8;WoK(K%ZYbKg zEwR++=5LFoi}F>qa8@m`XLR$OTKnHA>WV2c)Ia?bi4_}7hGQ=awA-qgx22NyTkOTV z_tY81wr)6vYgMWLjVd+f41fN&uBc{-dRHpen+)Hq6@;sj%+i0m)+n>ZszR4bP5ONH zhc&4z7)+JzzpFNim9xK4=w@Lcp0QWz?fYs0++0zGcYpEU{lyO*ioN4`?~0mTl`FNM zRjSP7(+z+2U)O7l@ZD#-R0iu&B4AiwOcyvMr^s7M1?I}pNbPZXq<{*Sj-F6(q=;$`VN_4$Et4z=h zuH&hm3qlZB1vK5Z4Var**V8S_v^vO!xk#}=MO(8-hFo?Dx&btIR1nHWp696s7^sVSB)4yBuHo1OUE+Bf z$$uM`NmAIhXM@JT-?Z}lf1Y1A49C<-zS<%e!64ADcre0rt&T}j`5gr2(21gsqHi9z zL48fOK@p?VM~4n#CpZ$2%jwygW_7xXL6Z51*odUcHN{d4tK&GJCb&RB zcBhNLydZ$Cn|j|yZjUJB+8Q_yWHJek1D>^Y5819^nIyptl?GY4;?dm88 z-4HK1z=Z%1JjWyUfoRq&({MFV&33?1KvmU@zH2)s0S;L@v8rPL4a)+KE%JX1;BaKR9Rivm$RbzJ2E?20$>2hb+yD?^3ATfkr)#kIb4dv%Dvt-#RFTplm=McF zd4TkCv_;^17~x40L{>C}FXSdT@kThr4%VGd&MeXc2cx0ojZ6~{9XuR)BjjW6!S3rr z3;Cv{*#-`rq2~|q<5-P6Y++;I*dZb8-Mi5c;{gu)K6bI;c|G&9>EZk7B*r+xgAtyh z2-}(&xY#x!RxoyzNQtrQtG=fXhscjCV4Qe(7@I#^1Op3e;Q;)M!+1Oh@aO@1Q4nBv zc<F~{S`@!?K+4^z=J z_=V<04xae~#~t;pkrmy8ep)zuaBz%=sr`Vk74;`R4jv2?1ic9?yMd{P!Gjir6AOET z&)^q~K;uwD2anJ@>%S(}3Wf#&#Nq z-h<~mfn)cPg+KYj?mY^}-pC5AXcSK|GGm+gH3)LRLxewJgdXGHnuNCDNAnKE?BF4Y zgK_LzaNq2?L)-b(^QZ18@G;!}qv0q*V;|!l4*Y2R;2L-mpfP-4&jH~>h&1cbk1b;n zXe6Nz#sP=gLu4Xsj2&1V7QT0f`2L>Y5#Zi4#J=SW13z>|T69k$Z!oaO2qPy7Ay{MG zi`20bxeyK>(#G1@?dbu8Q5b~_4SVhc!VnLw`v7a;an1WATRq@p4IjqXdel?Ju@nsU zSBAbf93;VKh*v*y!(f5I;h}@a5m+Cz7?}6=AhNY!0LzV_Qal}N(a`*CW9K2lqtu&f zIK>a9t@$9#<6ty^2v5clL~Vca7!BYQY17Z1HpNOb2nK#&WAq6-1MC}yJI2F^cyx^I z(SxDDeMuYloXH4mZHDS}>O4M-;-5o+j~@tDXf!ZBA$u^LLf{$ND0Rl@!5?`;)fzm**GyLp3Lp1V}sfTAfn8j~C{`lv=Vs5_(v&eIt|wu^djGT-S&V&?X&@`nj?sp&sT&>Frd`MR9ZU5wm4AlxW7nH+@KT!MkRx}RnTCWtjQKze^K zE@&zf%MW+xnFCbAA)fJx@Ow?7jWjAtxd0WFdJE^ zc{puAGr4nesE(EoC7v`5AU-%qV&~Cuvc`@eER*2)iW5%u9)UMFcgUM{6nUL=ckOAy)%Arsr8v`Cd@cDG!tq%3P? z>y_MEw-Py4ghe8(R>^w3jFZJ;Eo8|`lG8;d#p`sPELVacE31?gzE}!LDrUmA?u8^Q z1bHbYi&Yk{lPq1Nt5i${C0>fLoJqpnLfjO-$XfDBT8n8aip%w~O@Jk`)Rq-F5nAiT zN(2$4R$G9dcP%jikz}RS26^N)DSnYCB6P!f+5*zvWDQ1cgIz#T&?(N=QhVJ3=ZGz7sfcYMX(wrGN#GDm;x8qY!B%bX zZQRb-HiMvowpvw$cJ;$Z)v)RtMu-`_{g-|Btj6C=Jr~nf;T*>v7(d$_{uGyKXIuD#kobff2L$M}Yym~TAGIFp?7L3!m^2<igSA7fP^OiCGS~!wd znzGa7HOAdn`iQgkkdtlO3a5fJ{lobeF&8H;P>zVaC`@t8<5epV!&=W`>?`VIY$VWL zN46Z9Ro8Z$zkt7b=GN$;u@%nxKD4MQhYw;=w#dTR%w#Au`Ptp)3YmI5j*jh*d4=w_ME?9>(}r&ubl3R+AE7hMd;wG)vLyNA>s;U zR`_UMmM$wFe_7>g7hQqm$Elz=CsM{7*D_$||KyE%> zG;cptYORlTmVXpJvLo@5lDW=r#a89~pBC$kY?g~mnV0Gm-@3kHnR=rk6iVfiIJvDC zWu84RvxQQfE7BqS+1ix2M_MRSOsR5qQ=rb?mkUg#PL0_!`tG(#RA2ggOC?pnjk$2RAI=mC9P7ISe~K^R29Z)>^Y+c=Zdw0z%aa18h}9O>{+G6o?lS^mB6wRqw&=O#ZvFP zRF!X5OSd9TH?2ELC|zBCS153HiK~>kT8ZYVQkAcZG)tY;%5=TRTvEl4jL34u3*ic` zvBe@Ma3zXu)(Ry-Z4{bkmxW4kMzfXoe5G_&IIGbGR;&x%KVeIa@06Qr{XJJH>UYy3 zFR=XkiwC~&p>kGkmfu}aDScNfHmIvgU1KUjsYF#;1&+Vr=3v>2W#K{Q+yOT`AuupnmXL%mU8 z1?sBF@NKro@;&G;UyIBo_dBJ+nBpONtuyXjl{=^I>l7>0YE&J9gen$j`ie2C6{f^@ zYUeB`R4SLB*%BkMY=yHap7t0fWvCX%_u37Pqv*@C%W9LN&dSh7{Z5T$sCt>NH4CNc zS+!Iaxf00L@`9@Pvkr4xFVkGzTdeMAM_ZCV``=H?;3npXE>%uRf?5zo$bCWduPlK-BFeO_avU>9Y$nsSb`-f)NgMZ z)$8JWrcA%5&Po@IQm@qC^Q>HE5XGK1YPCz1I&WP_73#im&hmAxR4f+wCQ~oe>h;@N zlR!pHRaYGc9#x%g&#^2AxgF0Xd3?+3AX4|P=OEMQJGNmULv=`T1Wz^l1f}321doZb zZaE%;i<)L2r*CNlq^}{}vXDlK3-qlHl3juzK%QgUmJ8jkEqgY}T^oqh$k53v|9N`8 zYw4SEAR3ZUucOGe-07$)atS)ZL`c?12??v07bfs54@Ak!3J{`sqp=w6;Iba9Zaqh+=l@o*+$m|HegZ{ShVX98el90vJ=1w0k@b)G2D*pV2M!^jMPdq!MCw!^tCI&PK|+CwE(DB8f>AMby>Gi94eD8a+t6&iL+Hv~B9@j{ zbOB9?nx<*O(j%}S$FO8zXM$dR%P?SyqmigZq06fSd&pZJHe-xFr*|D#|OF*rp5q>i}(XOF&>Om!N_Sf-sp* zhS=3ZKf*Rfwm%|(i+e8^k)%BSd_TZL?3qJYc1G}MVXQ@-JCB@6H1*J(Z3Ld(JT_Pu9~hgM__XQu0i z{f9+_JvZaf=Prv;Uw^pPf9X8#J+p) z>xMhP)7}VMuyipRy5C3kbYywK5QD`d2anJL9!$r{BR2dQb}+;gMkB(@Bz08+Y@pE; zmbQrl%T|Ua{vHFjD49Iq(S10?}XQII>LF?CIfb0UAn zK6|~X1C9+atk*|Um1c~?Xrz;R9Ah8Zk?SQyHJ#KP@qcPjV?P7nD zqkO;&Gv_|EA3C$Z_W}?9eC$79cQ^_)H;P7+RK-p-3`g?)cxYoMjEv#;7AS!sYA{ml z8Cbp#fsaPudUrseH3-{N$Bi7{98T_C)98Q#$-~T2K0B6Yq0!iNRR?=vG`6s5dwvM( z9?zl#?nJ8R``Q$ipE(I#b2RPy4;n4))X@Dj4%~#m!n`Rm zX5WuZc?eOKfHmxJOt4|Wg9}EsXAq@uQyn{x4`w{+L6}Cv`1`Sk2gXE)5XCzMCYn$@!Ro5rRCyJ+bl>xNYvT z*=SSPAqRYTyEOT}?LZ7$ss=oSoLnP6j;j;oecNgvLuY#!?5|8Vya*#}g8}fjkc3Sc z1k;)LAoIAF*D@KY2cimyx}keiK?9LYKAO1x4qtQJhLe4!f0WPAb0orGkOLmH9qBEW z!G*7F6%S&CZLc~xpg#_%gFWJ6g9Y$*DvsgP*p63^MtIr@lww~sCEEMZRr0Y4*hbqF zSJ}A20<&1djRpGdo})gA{9O3HksAYM2iCSkM)%kT0f`AsgSaNf+mwFUN$=-UlG-cV zp3Y=%t?k%xGjsiM1eSet4eL^A=9CmjR(#zeOQ?iMxH=a14qzD~i!2_v0 z9JV16Y*0hn1#tjRokY5^b<4&;hU4bG&(R(S4RY^l#6x)i5x|CZL}Tn6D1Za-WK3alX` zA6u`t^Ifo$tGg!`Om;EsP7YiTJbPpXkIXHQ3FS=9SMV$U<57K(?iRoDcfT6HGKAay zZ;<0V1B#UIknY4pj#HUzd9sw-nH0yQL846Z3S^aJNveb_q)glv30cR|T5L-)Dc_-xA|X=TUbd6;PEN$E zo!k*{N|Lo(>58CPL@{12Tk&csDa&QL6y-ZnUaf`o0)`0fWO0{?>vbxM!h%!@5t2;G z(q$?sZ6FW}1OSp33Aww=*6}(ML5nn9Lsy)Lq)bQ(ipL9KwJ8*`TC{{rSV*9Wv{q73 zTinzMX|H5KZpX_NsS~mmNtuv%y%yTbwbEM2i}eyTN`+(r7lb6fTarQ{3lWTX7cYf& zyDcg}W>YCdR3r(grrSy(V6V8fT%?karFSi9k;$t~rI2jdN?M7uST0GelsL^+?KRnZ z28<$S>%}_DT0l-pX|Y&0 z|7H@?-`cnKt^NO~y^2J6HI=+i5$h+(@ZOtOSNAlkJdFS9cwndz8#p z`p*U)sOl#j+N(wuCMbk+T+ zJ@;qW8S=U7Qu}YCRNh2%e6byEvU1edea+7*JAh1HB$-cg#q(#tj<+!ZPy3^nndkYl^Pk8# zpB&9kw~E<=E1rMuCmc#GyrR@G%44tF{FOBL)6qx#ytc}-@(c%H&HV98+nH?94NnI_ zUhIPNtT@Ya*vGLP@ei*X`($g9JqF_G#9l|*yE3Iy6!Tq!tKSMPQ|(fBweUlQEx-G@xH$VcM_)1TIGQdu-MjSmsZcR)SfN$q z-t%QyqATCE!r!ZV><5}_gdW|eX7ook>@)O?{qXOym7w_@U7^nkrTZq|y9@;B`s|wH zYHkZeE48a#!6`Kw1-3D0P?hd&`;wzd!}_glJr>VCP%K^k$2FTht1ut=>oZnkt=oHp z5t!EWXZ6|-c7r-EwVDN{UZ}R-RRpSrSnbDBh2z7k_iUlgUh}1oCHkVxF_$z`Z&G~i zoH}c=Hv-L;u7=8`*ep?JZ8Oy=hAmaO;=6aVQe9*ju~B5$+v-`XC6?;k&EmTJ4$iJW zRxgEerBH7C{v%%$Dy?(2%(7fawPmK*;F*g_gZ?A=!YCu*LzU+05_?gsH*0*g#y3A) zupD>uiMeAho!{_m?Yjl_$G`WH>wn}g8K!)3#$0pEFYC2xlj6?H@2NI_S-g2K6@vmz z7cVH9sM93W|^X-GFK__9~hRusFbN|_5;Jy0wXg`hM}8Oy(AUO%w@Gy^v@Zt zRQNa1N3O_MJC*l;KoLq6o@&9Osj~%{|9i!2j^&tQ>*DI7#htf))8y+CSGpD%wNNjy z4DeI$kNC*A*8f}M|McDO~W)ua@uw}r20nRaC(OBYOO~$W+8NPQ5yuM@NeDgIz6 zWP3WW(ce)M;?T~sW zuC9^lA^lE=lqMv|7%i{=VCu;05TpP?IciFvSSM=p#j%T*ESI9lD#|#pn_DnKu85;drl{>6q4_SVQe;yA^H$xPQOFoCdkwB z4LDF2J}u3LYpQDjHw!#~6gcg4-L6f_w-983)0exJX@hl1SqszwQxQB6vWe>*y-V;d z2GR{uGlXDex)yR^hAo3)wuX?|1EX4?gN8gu&)s7wqyUK0w>^*SYl2LmXLan3qV>96 z)3G!#G1+~l3rxXTM0&SxqwOv@r0R?Z-Uf?;Ngd1bNHq#%cL@APAq8Gsr>Bs@6?!MH zi~=D>N?SN?ha7)VpwiFDaVR^$Y^9kwGp} zb;c(14PEP#5Q11BMMZkZ?8A@_LEw<07#4&8Sq+GU8_JOpU}v&JrU|O)FkNwgk7qdf zo-T%)?}@pQKf7i18hOfqdlHS!H#z(Qmb zBQQ}9=$Kujqk}8JcMhpuVgR3hUY!LgirEDhShi)^WJetv{^>b>2ayPXB|zMc2;?d^ zmI3PyxDr2sbYy=fL|oaoNkJVGL^U=QN6751V=87JRufFH46-;(gQ(ydrlqLtkI+^-2aGgH;xo+cW^e_s3@qj>-0ZH)VICOnGus`ASbAVHz=Y5)BFsuu5cy?@& z6%e@NPuAmntbvU}tUiL;(_rMotNI{tK*zAw|*z8YS3@aB+(k`A3BaE#8)=dN+ z8s3NQ;2uX1%)06Q*35fw(!d&%y>^TNL3zM}h6r=b$TT2qt$Q3>py9M1AcPYmvT$#K zA3crK%6Tw@5d5YZgF)y_;5X@rEadx9UXx}x35`^pM!FG9d<|I`8TX55X1W8i!HGGU zU<+xp2s^=KhV^=|s;YlVBT^wp#g2Dx4^un}wF!7E2qVP}Ar6zFqvOZq z-k#zyp50GKtU?rqx;30dqsdT1c4)dYh+!Pf?jeZLCzNl|;*7v#5sthu)-5$`1{StF>Eaw4S;%y-an{7he!x($w$cOz_a>nLF z-k={g43JMuIo#m`^bK7wv)8q^^FW8lIOOS3&d=BjkmC;aV1!_&>s~sSSa@J;>%Qz# z@wtfpc#~51o^SH9kuBV)Mg%mDF7`lJxVd>-%_n=j2(c+R&I}auX!ztA04O(N=!|!k zJ7Eb;4mQGvAgz<@bBvwXE4uaeCLUB}Kfq8X?q*Y(ZQoG=jhD^KonjEVgX8Kb+sYxm zod#i!gn`@MR)J&WO0?T_CLm_Dw?$sI)V4tnH%*A%jj(%T@Ac~Kq&vaGfE4yFlsX%Q zN5`fJ$W`wIO{5)dwlp4Y7#|j1@N6q4{jh|z$?@Jrn}#-w!=o*T;BTK(5*yENeK$DS zPKmT!;l6v)_X4Z&&wn`JGJ0FA#-CQc7OR0A-;aJn;PW1}7Vhp^;#$1R;&qlSNWqcS zVtq%7jbtKxx7SjZrc1Gv7aI`;L5h_H*_S1elXbFQWJ z64%md0aVv%vRovqY%M7QDI}u6&=sj70uv=k&d6>unUF0+NfMUgGF`yXMVc*AF_q$F zDlTI|6qeayNuUr}mWo2UT(1bzcGhmK7vhraHbX!j@=_#wn!w}~fq;gmlDYD-$8j*0Ct8g;<0u%Qy!10(616 zWM39i{3DhYzz^)PSgs_X*n$gbJB?!@i{m&GL0Yhrm`SOWEb>wxix`B|sH{kYnIxt1S`-$`#X5I?mMGv^7z?yPArTm7 zAm^PVra~-(kdhE5=|YmzOv;u^Nm?seD_tiGve6E>DqD&`Maam$Fu)#6oMkeE0QfNl zfy9-REd)}QWeI)+!a!yX77`Z=h=Gg%c@jwguA%_O6Jny-f&hHT7f>dSg^w5vA>J`23_QVYsU$2G zOX4T6+!7)$ONBHC%%r4X4xzl=F9)m(K?_2IYece5PCJnaf@MV%$FSF%ZSuSG`HLvmmwp+wx*%1Q( zJy1)85K8jmJ`h(BlMt=TjHtPWg+L^i7DUQqgQNn5vb?ZQyq41?EUAsOM!%XUdpE>!HOgc60S-4icCqQ5_#J3W<`o1WJW@Q#9p>kWI=-U zyjTiE5+Q*wPy}K&m@6qjG!tZ4kf2N2O2AcZh zx~d#Nce=6x#i=`N+-vx`FPG6en(-V)r{!07x+%NPEkv}xzj9#EI}ALa_4+$SjV`JF zroY&+?Nq>gk1}mvHmjE_r;{!0)NNPyz|q*U(oZzm9UU21-;CW|*dgeYyNYj`ajF}U`WblAJf^*A;7)BrTGzBwN%GCqb|Bh4q5l5j zf%Y4~$xZz@BH)(fDVlR3laul5T9GH7T<3x*| z3&HMMFX_M7ov!!d`m^0AmE&-IMc~s*&(+%a>@6Uvc+w^IR)Jw3A0l!I6&Ha#v|x8LY;$7+Mm?~yU4y9x7tPtjBo zsl6@?-+_Glz2~vJ6DjY|j`h%wA?-VrP8EEO#>?B*PSW0XGf+(fDZs_~-i-P)`1?V# zuJHbFDa-@2UM}Ni{2Tmt z_urh>W~7l9y!--Ee5;%CT*iI1&l8#2@ZIfnJ6rL|Z!$xDQA@M0D7%**cBa!^f@UDS zy*;`GsQdjQxdf<72ZPLgcskg1-c>KE} z|J`wTl|?V-d$YnRcDC$PHS9Xid=Wka@@0gge=cM-bBcE?_3kqsv z;#Mb3C66s+BDwinCyZdECg+>nlH#k~e1_Ts`}XyH^;C1q;AG#@?R`Tbj}}@xzd(Lj zbzv_2KJSvpsP@5(-EMC~Ip?{HvmW&JwQg@452vfMmwVJa^d4UQ&`8}_eP8BvYp&c_ zS}vNLFV6f%vr!d-ptmt+9y9O^mxmk#r@ncGiR|E{Jbz>1O=R+yOWM8lPQdFW5%*g+ z!od^yH;;EO3p~xAp5l0ZsFE0OUrl)NhQbS8UnAUeIiHT|BObluuzgA30M|Y+J;Gxj zxIXTV^LHBNFRe}<}mdigHGE7dTco_6n5%%Ar7_`L{Ed-i+Y zhc_u+dt2b7ZQr~&>;@X244rSMKF;@C9uFlh=R2#t6+v(GZw;3dKE3kztgh@2&y4=; zWd1T(wro#b^-TGv=jCfRGhQv{xtZ|gO?zM2>GzoS>G0>nj`wz*pAOkB6tbSbyxZ%x z|J7F@cI|N&;EyjvI2G_9#C&_>h+i2tKj}HGZTq;{7mz-Z8N`~zM#ha5yi}~h_!l!M>!T00QJBGP6HjhV7+e+CxXXW*#pLVY+p8766eOvRGbN&l? zzSZyO;yxDVyJ+6oX8yD>`{V!9-j~Hna-HW@clEw+ci(TVr_QN;?e6OC+kN{kb2%Hy zAt?^Gkwi&cWl=jR>qtY5q#;Pll9LFsV%R`7_`!KeAOu-p1V$Xg319?pV*4?GUy_F) z4|&VW~Jm$g0xtHB_>zwod-@lyd>VKIT=-di`kVP?a_WmTvS!2;lg;uUy z-cF^{nQWEg8ho};$)>mhSI8C0sUnvuJ+q&xuha_#0jD<8JLw#s=lR`qtyFL2P_0vca=yIUT1uz3GHXjF-$r~cv(9J3mDEzDR4!z58+FV{RjFO!tK8PAl-oHfWQz5g zoGY5?S}LFCRyxH@q4>#4JzoT(VdoO|7v}W%hj5t9WKn}*H&vQ%W`_V zpyjJps@B@99b}rRY=5#h3f|05w}iOG6_F8Fix3X*(_KSRRw|ec1jlrHk z_=;6*6f?D3xxQ=O{cfg~wVvA9-#t5hdoR_v(RsA{rB}n1*4a}_>F-yk{53xHOb6wD z#C?4~y;>-}Q6SSsRxH;#D!;W$)@#N}uya`W8o#u?SFFlwzy8|hSFfcHpT6D@Ounuz zU0mQsgU|78hp6vlUa9Y=LsYEoo7_0%5k<-=41SM=U?=6b5I>#y_s< zr=Qs<%6VSlH?mo@RoKC6H9q4M*K%bi{h*Nl%+Yd^i+9*LjA~q`R;zM+u2@>yPc3Cu z>ou>vUCh_`pt|Waq-?3lud66y-Q^0)sU2e-B-zT8>l+)(Z~n<^!9TybpI!O>cIq@; z7-ur4r}p-KoR?~*mD}RQbf%W6FK6?)T(gobo$^Jn2QFRLTIojQc%2s4S&AAK*Uayx zj6K=T}w^cZ&ROCY{RX z)LcHu=1YxqE|bkPw(19a`#yT!Uu&m?@?NI8SubZhgwJ%&%Iz9|5@kx9Q!i|%3AY)paV&xw z0Ns9G%4JuoUSkKPiaRY);4&N0dez8gcqvmU-pgF`)ru=_)tX#k7wgkpY8~-hUfHO& z8rjTRBehcCa`sADOV`%UP`;HaRyMxZDV7RcmFw2IT&7LZuNQLMXsP^irkZgZ`(?6` zYTYcSNNFXG$Mri|Z*qlNskyf3LFENH1mh z(po#UTKQVa+)nRS-)~Oa0um20o2kj(?kV5-_BX;pyV1UuyV+dNckbZHO6p~PN6zVG zEwxe0$?4l1m#dVH8ku9eyjI}TaP( zR5ns&lHV;)IBuns$u8GBRjbHv7q`~yjkSDOuSw~!kmLE~HNKLm7|IGL!d^2!>G0)D z(aT8r)vcXY-L1E?+eevFIs<-&pBnXCiIW;yr<}_+(nYt()i|-vaY{;W*K?iYGb?=` zT-qt~jHN7B;@1o5T$wAR^EuuI7>eB15~y!BmEp@!Z9ZQ%vd!XhrPOZhW((Y)-Qu#T&Q391%N5IwVxv&aD;5NjaHRg&E{^_Gkeq4PKVo=q+dA_+NHgn zN{)+`w(_Y?AJyX*rE_vp2rd=uQHEIW+ zIgFI;9Zl{ZOY&gnH~gSrovzkSb8@!0`|it<%uhM1RBF9b>Q=9L(#e{C^B2*IT3Wux zFV$g+bTOMvw}V?|_geMV@yCCB%eXC7-Bw+DQ~T(>ov`cw+FR-Wz;Q_3`sH(X^3kLA z_V%RwKWcBBoaGOV=J3IiNHVWux`%A8?yXFO`0Yo*(R2N-ND* zY8#nmvvIT8*xtC7yODkFFyF0yZJItdP%S%-R`^YFlW%PyM{H)#%6cyM`gYaHWgo6B zskxi&_6J_0R4MFMzSG{D<_cA5r@s8z7U8c~-}+AR4*%4<_m6Uj+a$z06T3Ih{>yUq zy=#q9^R=_B(s;7*gE!mjyZrcGcIEc7t*z|Iq0~%Qo@qYUEY(T&NOcnj#pMPhsWht-ut&F>Cd+{Zu~oy%Ie3h8?9=k+$#L|%Z2jR(|kV5 zujZTW=H4Gh)(zzxh;H$>ikS?`>qq`Pxg<&paJQ*RLOHmH+uW zOQHVt9~8fX9=vz>$CYpVwDi;1|K1Dy@!7MhgIuAX)~Az#b@uvypL{Rdz5gGPQvOFT zjkTqt>9b3ByEfX-^j}!vZtk>yp8w*l!ZSIp0b82*!wmP80vEjh>o4vf)yMotUy-Bi zy}xcK(_Va%xl?|1y2?3U{@hEi@_XE)x3ld+>$kq(yn6QNKmY!<-SyxPe^PHRcg{Y% zovB}Mcx&Nbf1~(X^U<~D%1cXAU;B7}>J{VNOtpGi$?1`?Dmq6;r4_aM z)7%H?O6Bk``QLqQTsy+;Uv^KvUHRb~UwFS_)Te*<(GT9e_p|)H)YHemSoxCw=6iQ_ z7u$*~>!#+|#Bv z!lEc(f_0O%p(lo}V?&jYArQe3b(v_ot{H}*5mna-(J<0=WEi?B>+lVnRb`?o1Pj2a ztZAAeNunSK2#X5*13-`_sRYAC7;8vSB?3SI%}6su5fL^>)L;%l(y*!ltqNd@iKNJy ziU^!Xu(T`yssJ-4L{x!vM0CIbz|kd5ChR0uG!TXaOJEHHnNX@MY+f-D{D22wSk zL=$vkDTZn2HpmD|ASxhKH&iBexBwJOMvO@!ivlBC(Ga{B5D@_!L14OKfZ~8Mn?MG` zjc71f(g7nPfcV(lpe6+P(p5tySj8}>2vEUHth78f3CIRy3o8=?>tHEJ)|sXQc|Zhk z4oXizpP1f&G8#nG7{tH{E4ptGO@d*v0tA6h0Ry1Ipvi^;3;=|>$bccX2Jj-FTmmv2 z!@vp*(m~=(CYp`_b)Z}nfkRyp6cLmOYal_1h^B#H46DbkV8b#@VuI0wh(K*X3;-sE z*+Aa_Z;jX{Obhm)sDh*@@FM{PI?;8DnV~5I?LZtLq3Q5XR18VLpj8NTffan$90A#Y zkSHsnB+CFIcoR@9og_RFA_E12rfVQ6AQOZIK0wxiNel=eP)0Co0`p>UIxtuQ&?Fh0 zha>{Upgve-MhM_1j1#8YAbAtO$Eqw7X3e4^10-3GP|a1YF^L}G#LK^m++f(XRQEYaU!4ow4B02T*2 z226nVgDVAG6!3{6LXr%627+cDL|}))Ae4Yga5$1Cfd+&8z+Sw(i9nVFJTrzxK|8={fQ4ub08^k|20?;0fB{G||15wm2qMrZv-gY%5DX|H zOY8?MLDj)mV39RqQ54v~z#d><6xhZFI;XMi3$$AWX#jB=^CsZZG4O&xxitlY!yvK@ z4ndO$xM*-zG6o`KKuuyUgdhoc5oMSU$dLv1n@z944lXf*WiVIpb`m&mSb^;fgvEfs z85PtS3oIOjsV{Sdum(z0AlV7PF@tMYktBhC222EI2Z@YCrZ=GJz#3>L;DliZf{lD8 zv1H#7*(L*=0IVtkMFccp2Zdo8=n%Lopi9CG98fxjF}Po>8n8<+R|z@|1}(!r!nkCE zfHc@^SW6ASA3PX%OR!M_dlh&~W`O_@GddL<0^5$kBG@jXF-(~p6;MP`1*x+7A#76v zQw28yx&b~|1aS+nV`+jWfY`w85D`!UK7mn~0rmxnxlM2{fD>$vVATfGcO!8Zz!hK# zG6260+NOcO0wJi1!t?>m0X!uzM-q)>cQn8<2t#J{vi%fnQDz7MR7~$x8Po%AFOoeK z?tZ|%VI-@}3xnX1tbk*L-ym?10MG}91M2|z3hXK{1cBreWdth+;VNu91iV3KnP-57 z!RvvW!pva;Bd}M%K7%xNmYo3?0Jg*WswhApC>{{Yd>u^3yoktd3UmNUVi*JL0-F}@ z;6SlKC&3s&kwCpn>g~%GNE!4H_A9j)cvc|E zR93s59P~75ht#GT#k6Z%q8Cujw1z(Eg4ebpht(jlscXUc0X2-!BUWgrQP?GLC()P3 zURNK9v1?NwKGRtPYD$67wauYTb;&e6XBY*h?S^3>0Q-BIY=^pQj)^z+VFdMh(a`T& z&d_zNuIS*2+V^~WWci`jl}2#?;~vSr;ZZ&Cu-~O_)RT?AgWMhpY*!^FjY7+zj)S7e z#!+kujz>+`qaG+`?C2J@y1r>@V-jI%5BgSQN?jU;7*j;MbgaS6MK1AhUfB>j8a(v>_z7@bn7~At@Q}d2A-Ew-7qj{|MgM}TW_UMTd4*fuN z9Xd8bpLJn5)FnIUJ2cWmyQ@zu+dBZ8>^fNKMuFw@X*4iYZ)gPp+!e_*bdE#X)7`+b z-I&@D08eebk98|NpkvRWzB91>Uf2cFE$XPI8EC9O322E&sp1=S2%czwi0SlL_ZPhv z*}y?esio3^W(Nd?RH4MPHM@^(9~nNF0X6$Bt9e3A(DPA0veZCz9Kgvp?Savw$R&my znWjDT!k#-BQq2v#Ug%qXFAklcXN6AR^*j-DaAI_6%sLwRJ}eD790$XJ=8&CHAAx@A^h`U`(jwn<&K8r_MN1JULS6kRD21 z-#LI=Ovj16Zal)#VGk+P>Uyz-jJV&^x?vQ^k@b11$|sRAuzIdVWoq`WvGy#E-1k72 z4$asE^8yJ4;TUw62A&yP!N3G*8^EDy!z!T_QRgsnsA+Uv%ZI(x^n27AjCv#rhMHs2 zfrkSMa*X>f0=O|?>H4FX_^?pdhRqcmh2fEScwkr_yb3^l0e&a&!Q=uJ`7weau{#0D z_>nBzwie*XhKsQQVl}7)egYh-IU<2$1g;tC5qu)HLOB@0gkVz!h|>xqGtd>6g)ns~ zJq1;esVB#MIu5}AdvVXUV%VH08OhzQsXCzns}jvR0OP@+WfQ9FZfsE$sFqHt>xNXb zZGkwhOC1q*Ot3Wj2)Uv!YJC`KM5=B+bp*sx?2@1h-qV=a#5X4{4FF750>}cxw}D2z z51hFDA$-*L!P$nsZ4C9kJ)ogYRM*tIu4Bfu&wAdCC^!-+l3btmf}W|vEI^m(xVqc( zw80P%9@#xV99i}dTzHHfr)L}+t`%CQK|Kp}XhKi@$UGd`rY;-3z_JE91@}g}8trSo z?M-9PcIo6~1Rv|d*g>8l1mIt35P0AXhqmt!3SxDr)$@p9_2g(WIRtM#WR<=^X+yVr z;GI}~-SvG3HVY?mhi>Qqs+KnPEZ^}bithO!77w3BhGm<+ZcB8G0`MlDr$i3+DKYzl zkd>lxL!-yaI0fClO9y7;IbiU^UIe@hV%5|G!K5L4sCtoo1}f~xdrV7m4Q?A8y0 z*am|1;~4kMK5IdZ@z7@lkGgJe0Gp;}Pi?d7__2e#2kwE|54{lE;M8?z;2DuUa6(n{ z-M%B*@Il1%?FfV)IDo4$0RN-Au8$oN4ZHdQyIbyh=3(qpRxZgL(J6CJaGX%vnnXtI zxIJ*F;6nq+2tgMSwwU*~U{+TLg)@9=yG)gIN5^(x4&4Cmz`&j8;Ma8d0Cv?r?3Cbx z3b$nkxNNn#}N&>!w~Fh z?0c;JnSqSZaSr^61)r(F!x+934Lv@I0K)8m$WRc zZ&N&yOwBw2Zx%YHhhgLJ;1+=DY7Fo?9*Wi8u|p*@uryP0uxSp0Q_VfL zEm!efUvxC^!7`Y+7t)YMvPabbb{Mb?Aixh00ym2MgQ#!78iCgJ`!;c$C^UQ&;E@A& zJ+b0x6h54cgJ?uFGYkR%2X<<$>yiQX4*KS(s~EtK=>z<7+>1=>m_!C^C#UPa$?Dj- zMiglBfO>XdvwJN-yw3^|buAj2pw?kP4&1<$l{g+?3-!bBfLxonV1{A{$sUbW<_qI1?lsOD-J8NW3WOo^W!nz=ad?3cv3B9QBi2N zBD{<61sL-xFLrzmDM`xHsBw5c?~MFey(AH6|CCl&$ssbl7UgJAd>L`}s{i;nY4Pg< zEon}Be7Qwde7P@^bWy9xUtBzAbWZd1TSM)M~sV^11!ikP7>KK{HOZ!T@vWr8F$ps%X{gRmMucF4@oh#*)$~;PJ zT5O36avW`b0Z87yL?v5<^m|ewefOfJm%6A6rp%>yd1>jgYA)JhC5N_Pc!uA3L$ibu zpw*V*Cu}iTobvi?Eq6}!0-0_+Zzgx88rh|3Y$l$^3M635W!Z?12)DFsO@h3~{K{j+p+4ofbiGevHAqM{V%Zbt zHjsD&`3X03ez5a1eGq00n2!}66B9rZN*E)I@Z>$atatU&OYax2f|+34xHrRo&iA>& zCyRv_q|A?5BQ^G0kGl&yxmvU8ya(G%f9*LRc5FE3gk$-l#@Jl5@MSWt9$4(pt>Qvc zeMSp_Y%biAnXIFzj}PwlXME1fcEt=OH?d8aqEF^Vzfc03T{Exa)|=7B8W~=a_k6@c zV-5E*)$^^TJ7amquRa?-WAl=0@so;r3wo6~_tAwuhBI`cL@G}j&U&cYblwRT3?P<3|Y-5i>H8A>5Bmhs2+@%g&G9B?4N zmMwhJT}vdX@0U!jF-47Z-H^OFW=>BF6Sk%J@e+L9gvEI+xgJ@}?aU!k7Xp%l85y$5 z*u}F_eoyq=bQij*&oRDWiJ=odetmKzQ+dh4y;w`uQJutLIWwEGukdWo7fw$2v;E;5 zp2%I8)SS_)_fOV^x;~-p$*wcoQ;dY}^WKBnymg@8?Xf>N=YJw>nP4%NO)bxLX`uz` zoOHC%5(h5PFaL2dnQAOv;wNj@eb9NbcHKWt|3BBRb8X*x&2}Rv1s!9e#lDPJ$yLXdob;^?oaMN=)n7=v*7fh zxIgVYWWD=XOTG`MDx6}C1v}Hz`>T86X=ioJN^x~2tRxyM57&YD@592)`wu?6fB)f! z4`GVaq?sUGpOk82HSSiYV^%k+$?B4w&ie;GWd9zB9hFrrZ~j$!TQbn-xD zRnR`1HpiXQ=Jdhj!D&)k@4@u`Lsl4#^%k5ySY@Q1Ht(OF?yZhbS67>?&eem{`?Jd) zehBnE=!`qF#(=Cg8*t8wlHCWe9_$d<2@~7v0jZgBA36nG9AIKz3x7 zgX!qAtZeP_gw93YG+_y*^NI$Jv*=dEa!St=SU)Xenx&Ge()so0si=fywc?~)fOfIS zrFLma=CCx&Y8TPP-}J|G*XPaUG)GitDfsHed5x88FlL;dU(ZrUH8dkSiPLfBEwtDR zY1Yb1Nh(QP0u#-ewUOEEEMIum7;Uy7ND8TVo`XNHb#WC&IE+ix7G_=DW_1)83g=0> zGtlJ4yNfJgIjO9`C;&0a>i?xi#p7Ais+5$~V1NU|GwIJbnB~C}2P0{5F-pK;XU{XZ zi9S!eW*N2T`5z~jQ}U8D%fs2LODP@~2_KIovdkyAlI?Pyewif0u~eHUnrNMz9Ns)k zGE$QioW&IvIWCLj(j+_N(z=Hyi}a84oSIL|xnw*f87YeluAAq>lJwVEvgdhX$psd7 zW~m{wQJ0ck?mV8;HBX^AVaX(qXS&Q1VlE+cGfD9qvox34>62NS+sS#->^%935q9Sy z$8GU?KHHsHn$CGT=$K`lom^=v_E^5s%|&Y6or}MY&-%b%Oo3z-H#1B#c?j%!FRR(=Z@3) zwT7}$G+XzY{X3O|S~bI6OXsci-J6A8u9&OrWH&oYdk;SMl6X6%@2wqezjE}x9tn9N zLq2qFtbFozh9AH4dQPvEOWuu_+i%v(lgx3WJmp+L`rp4;l}go2JDVz|B)weWH@c@k z`e7^ehktovTHX4K|5aSco>opW&lhvq_suVEev4mAk=%c4{c7{{_;B?&xACsuIOcL+ zT<%nw#aei>mzp#`pMAL`A>7WrS>4Y6_VpE|+2#t3eArn!;xcA)`{eM}DE%jove|gF ztv$b$Jxj0ba?@qGdDd9*ZY`~4_Ww?%U9NvN__owcuV-$*`_Wo{>AUqC(holQ=ELRP zKkxi`?as5UNB`ng@AO^ETgk2-ojt#{vD~f?Po(MXU{%}qpIiPae{*g5?e#zVCKujq zZ5*jPw}p*s{N2+{H2zKWlV*?0IUAjEv9_CjuJ9Il`k8AV|IuH4a`v+J;kEWhH=f3~ zjE?wF`z3wFNjw0tIw^yz9+kd#x=Pjr8)8AT6Xot%omIImU3MAt?oZ4 zHuj$LtDk+V+EKnzwcot=j<%O}&kDty{E4{yqMpfDGWoq5<$Rk{@=NX;-efpV7w)c? zG=5Smh<*;Ga=*Bj{r%{x@$JqBpZRAGU**&N8@Zsd(HwsAuRi*~dxu-U^%3`sQD0Bz zv+2{?zr6l^!z^{{X!>8j(0c2g->B@Im9k6ug0lVPE&PVEQK{E&aR;}{N~2bIF3 z%`g4>;f)pX^FPl1c7<0{$A$j4KD+U&ufL4bZ@zbzU|k_PvJp6S6|0hpbrub!iIOO* z1gQp#az(PjLTPk^#ce8rEGvqNbV*}Ttb(Lqfn6yf7Wjr?Gtm?lrpW?!1QtG{2ojQ6 z6cmfn!HR;CATL=F;2KdCU^-C|RGGziDHsM|O++lP2muWui(*155=0g&!h&;>I2pvE zWF<+JWL1pe7?EX{w-zf-J&Su;&RZ z@=7H#8wtb{EMQF&SridUV((bkm8P)pTT#Xg6Bey2B7p&-C7=TMG8Pn)ggz-?i*Toa z7^N(lRz|X<36h!wTfwhIERm!EJc3^osDF={L#O++G- z9}|rz5itoKL@Xdl(~!dAf+QA)3{*21Wr2nANh}sy1qESIodzh2W)g$FLj)v606i8z zrobB(bd;4cPdp}Z_kOTi?GGGc*@AQ^@=j9}5g00@fKp|VFLEr`AujQ-6PlE&ho0|IpLLCK zv{>~9R%C^G&>NW8*Mq1aKXi9$Q zsNN)i+hc#C9)u%{wNA0U6TM3Z_At^1x~=rOE_J+-NezpJ69b`1VAw7;EE1Ro_UxWT zEnOS=?l?9h;tvN=Xj3PexY#y&)N-k&V@DtMJ=N`dB(kXI`>wBAFcgz63+OQnpaW*1 z;?QzsgX*#DsucGo)p*v$0oLCMW*QlwmmW}SD~h>4OoAW0k#hU%ZSW@ zG4(86AG6Lsh8?N4H!vgH3f#aNXkO&|zD5TY3LQ$1bQ<=;E#dvXNtJc~8o@+kIg-?ylNiGN^r`!2?+X&Ee@$_WU) zOJkKrNDpKT19S&@!6bI0@F?nq=7DbmhtvrS&pwWkbKsxET^IL>=}Eq2`9@&5k!xZ# za-1H!6P@&lWqPMw8xKuK@p>LseLM&~#q3I6Pjh|W=sMv64Z5a74;J4b^1*vwd-hfL zZ~O)kqvX-l`Lm_-L!Uh|GG@=R7EcNL7V8Fb@w`umv7&kYFzez0vcn!TvJM+ppA-^t z@pNkT<%RBF`eMqu^!!>Hq*AiwFb&00000{{{d;LjnMcZ|uEUjAU7Q9(H42bGea` znUPB^5%UUJUrbg4^fBmJyj*JvF2N!$6-xWk#HP z&iR*fs^Z4~-S7XmYZ&&)tlj@)P{FV?R!?2^VX%E@8H!@Ot-6Y#qF=hA+Oq2Cx~#nI zC@L03Q4Pm08{_bj8AN0_!mH$97=>i@vRVskm!rX$iO6~t9}dT(`uK8)4`9!*HmcQz zVHnlwwOWLam_ctq)@$QSk{OK0(Rjp=l^R~H)f%nOh9QJA>k|BrV0Y0pcq2{9oS&t%o zJRFaEgWjk%V1{^g6o$2WuO2oUiPOR^gx#SsRj# z5n7PBtTpf&^W9HAYoE2x+OylE{*y1f=i1u4ih+IM=@Sh#0sY`8P2)9In>Gsl;9>9l z^{g@4a^vUI*~KVcqqWu6ob(9XVmiIDB)7COFK7bAF|0__q$bg;0w=2RBB!l3?pg=4 z7(2HN{^VzJIi#QO1LRc z&{i5V)sDL5(ya|i;ik4w8nYRnf#7M9B)IuZIH*ousR!+1=UQFu6@!M( zb>XiWuyitbr1pFqH(QcHnk^q6@k*KH6;~``wCn9k#id=iHjPD>xY?QGS7u(dxF{pI^29`T31^7n30u)2?v-V$m)p3-sgJ z(E0f5E27^Q7w7$c*pK_+MU3982%ik>_g6K5bFOvFHD6jhoc_L;^k1BZ;bL$&8xt_dNiu*{fl>u`v^e^T{Pxb6CEWN(a`E|d|ytHD@r?rbKaq(m`=iSrE z{r<&8cqIb*IEF2puO3bgz{NtRi>v*-(sA;7{`TU0RkJ1aFVLuqrT&?lFIMcmn%ZCa zwcLHv`~9nt*T*jeUd)f=#qy|Y!{=|q^QCjVIsiEld;g;-M)%H%y+S5qHPUypWh0k* zFZ1JECSSZ)N&c3BB~s@lOt@2Aqw-t1O1gY^ovd!#g}eLNH7u3cNFhu*W&4#gKUr2@ZHMu%|L_l9dh*FX{-i?E>u`2Dlgh6*OFL!kXfIpK-sKP1 zGWQOu1@ghholG%K?7sN@LXNIyH!JC#WOlpqg@0Az@)>ozvc8SAQn{^-Tz0E@?=VZ{ zxBDBJpW!qAsM^^}r3%}-Tl@ES8`?c=JCWV{MK!awf2WXmr+AQXxA85ln#_DiJYZAl zQp4R?OFzW!-ru;J+j&}Y#Pr??RmAu3`g$&17Sa-T{x^&JfBYltAVKb}WfEyDpGZ=L z%Hf@2Hhe)lT;CA1Q>hYh#C95cDVND*Urw)|#pxWL!83b#ytaFQmo}ocogW;faaVkF z{^a|KTyZz^$LWpl9d9J*e1`kd=L^MDGQB3I3zav!RJzdL!`S3nv0BgL>pR7bX0Dsf zm=2#{*4Fn^FK_&_HIpoFeEln>t-|`tsoMP)ihG4l%*2ngK6`uO_Y~ph{9!vUbrR*>K2S@7%#boZNTF&p~qmur04Bt-d zirE+Mr&Ik@GkcN8$V@ejxk>EB)cVg9x6AvRIrlKPv%i;N(wkVgQ7vm*nIeyEog_1& zkj!spv+h=@*4aoTDyfZfF%u_496Ga8P!1D?GI?6g36E<;)441BetJDs*r@F1KDU!O z%j!}NW4|pG$Az?>~JaOR}b@3NOfl#Bz+pD4MD$swxU1r^*5aU&(^1s+y!}s;+6es?r)E>zb}} z@IzBkC5faYUM8A~qH&7GtExmRaFVL&@Hz|E;3Y{CIZ75KS!LnUvJ9^hvZO*$j4WxA z3YUQ&ce26=O^T#>f}u%@ASt+{BFmgC2$YOo@$j!IFr=)>@Z(d58u79s6R=lN2~ChS zm5}77z={$jX{x4@l7ehg1%iYt@hS%`lSEpONLEnLk@%)6YjCax zby8%35MdvuLQ%*Ctc-?}&Rn%k+xj`h+KErdOAiFh65Og?P6C{OakjGS|sYCmq=b*}(%E6@= zibL<yE*kyjP8m9mC?`1DC+$C_v8 zK;z>MXz^`uWLX|_+_FJi>-ueA2O8`%0^jSlY_Y8yT?g2}^ZZue_rO`tivrL&rrQ8S zylW2>O+Racj;0mvh{XhXd z5c}<8Q!=F%@H#+MT;2hL6A>H*lHmhW3pLpQQcJf&+XkI(yW4pHyq+2aaH--sTdWI*stpFE#7T)6gO!5Jpq6Kn2{)2R^S00$SvPPT>x}| z-VfZK-(jHJ9HHfgs8{iP)9H47!wq|p#n^y$Ld`u=48N;Lfn!=8aE_t%UJw{m3jiaO zBEZ-N@Wrrg#&FjyaNOzowj02IQmPjo!LcV%&*?&g)wXAy_|`E9Z3hIFb7uE@);Tz7 zsSF4l0L&vFII;xy})S$Go*p(^?(lo&jX4d*rwgpp;cW# zx)M<3W83PYcP-nB{FY;ZQ&ZFJ4%8KRZ3oJ+tQa2g@U-p4#{lSYn-@U)2%c%^e(M1b z_cG`NmJ#(ps};03(})4(16$MkYT)@H_O*}V#M3W6uBV=U9Ah7UE&5U#!?6G7fBZ1~ z!>9jUS9|%_!lwt{3qOAPBzXR2{S;%bn)vCLo452apFV}X_TE9NQ7c`-ZS&m4D}Kck z{nN!gN1H8Y%-%9{d9wCtv)pI&&rG@UjJyua>U`*tb4>%;rA-^KtU)Prvjhhfg~45->o_fC2KkfdR*G z-c~JB!>ZNsC>&R#DqioA_?V3FVP%9zmzVWk1Fw(6!R2^d?^P;wyk3tOCagy&dS0oH zYWTP@xFpB;xIT);;V`<4LL9F(P|&;{_V6JN*9_}S{SqHnY9Sus_!x&jFRNj%Hykxa zwP;vpMtHAMt2Zh*9^&I3ls+Dz0D7%*8TP6@9QF+AQN23GhgB%GGO9-5s6HmiO4zH{ zs&ICrR>Sc+-lz>oCaN&R7?cx}|EHSlVq zHmYBa!x6)fVXaoLh1C#;cGd72R3r??qo^0c9_X&9##DyA0ZHQIcvx%n>h%HCZ~%pk zpxPvKPOUm%#{ZuLTt91{wf`TrYxuw-s=o-kQreBS(#7B2Eoh`Li|6w5`0G-@^*U&P zzN3j#Sb=&*ocC&F)I{miN3D!siS*9ih@5zRu8t`uOt)t~YRN(b5roU}(#f0n{6<^p>OZTye=%DjoR3?IY~K=TzqptN zf#aVL0H4K!pAitgb$tKY`-xW9v4j=EW+Vm-Qa4VW}-Vf2$D+kOG zi(3a@88QVsR+jAFJVoIuj4;Kt`g4EHG@1>VyJH#hxY~mL#WMP^V&McOKsVCwdrm65 znG6O=ncLh+C$|)7E0fw~li7T6Kew69=hjGSD_7c;_A8Z~?Z1+Lgq?0<87z?w_@rOX z=P>I2(OGWe?KM$c-?_h4wzqaJa(ZE-if`|22zg;Ym)^?8XLti&Be3EDo;S1MzM0Nd z#_zG8-?-b(Z^jPUxg(U*yQ#`%VNlMj3(4#~Vyl#553p=zi_ByT*w)5DCX?GuC31x_ zewVCD*=#<)bvKj1)=FFTdQmB_70apIej%6KFJNNvZas}12x0caDDb0K4~Ey?l6(I^DsGc(wM8>HvO|ZzP(; zrd8Q0shjHGmNzPeO}*Taib|YLNQv?0?_qnH@_)7#ZxT5*;T3jH3b|d}EisSjgJCs= zTWcG9ro2P#ukB-oiXCvt{2`lQQ_U#jt5UeVLCcx7_^6S6y{;W@uH7l$DQu?md8(AE zmB}Y-51Xl6=6^pt{KEzKL;%G}z%2>I6wpqgR-hFoGrF>!ge*54sd3vz5m)=NgNj6`>8o~MYj?CRF zuTx1qvEFI8F zx-N+V%_0CmlXzC9n$;8D3E}LSmtkO^#Ppjg#PT zRZ;{&Bv};6)^rK#ps_4mPf_4|l~6PW1&U=w<^^VA4G)c1L{?^$Cc!I;N=d3Ha&l7= zC4p85US@fb5;>NUpzC;6WN7FPcxQn=?0Ez&F!}_AP!vK_2wGNE7RC5wg@h`JI#gr= zDk#wRG>ZI-A_HB)A|yaV(Q86eQK%dtC@6{#t%u9&ssOtb0*aIsC=AMC;Vlewu7n^P zC{$5c2{~DyXlOj_;o<6v3U`gB6cHH=eaNel)D#I}f}p50G@F7;s2oCqBm(+FW>ra5 zL{%2Frl?9X$M6yXwQM#im5>!EOqx7z!SQe!LXV(M48e&q&qD#w1W8dCxY-hq5Cc*o zX;Gm`sD>i)2!Y}zIKt!>3oZne(BbNE7d7Oii3datK}sA#SyYYT;0_2h0e6U2pg0zx z6wu2}MU-TMrCEuVB?cyOEU>bJV1-jS?mLZ$2XGkXKwSjLkf!Pxk-`8xzKJEh5*L>NtEC8A<-2sjRj)4G&#ckjK+t>NH zV|qv8ndxdI&;`emTag@iz;yt$(e<^!RL=-C0K5u-(P@ED1*W9~!?rwI*KIK9o|v7E zsQ}0C>2`1`wAyAz?kG{vcT5y12ef~px7<_N@Y<5q4r1s%sPQ=fq220Pz%t_q>S6_& zEz96k=m#y^0JeA3*8CO#femL!z*PMhZdMf907{1c|9NnT3-=Cg5CeaJL7M?#7%MH{ z`fU#Y{}g(|?VRWi6DZJN85#utn*I^ogElxi>zkkh49gASSU>W6otE4|m!MCX9M4fa z<;XVy=y{&o;e18!oku(mczE3XKnMNPUI?e0S%5u>T&oRSHPQmDYXXGsw0IY&q3d@Z z$nG32_(t~W$B$o3JwIN+Jzuo-)0^`=y~gswlc=|H+brs~&fD8`(zC71=Vpf4%W z=ontD)WQ)n9u8KR1*1j}#rb=a@cf`!i|}!+Hy#ejMy-n1n8A27tc`2+>S#Qikqhc` zc0s)sjmEuj1gDHI$;N0rhRZJq2F!Sj;|(%|lf(MBJ|2db_^?v143Ws*C5}h+!R4?~ z8%5P|7}XoK-l!Ii8MtJ4Ip-JDBl5C3?$wya7-yIeE*?eU;EG)^xV#+o8qBadVHb?Z zC3*oIjWeTYROvM$X4DvyVHrRJ^q2u+84RE{qu~gz z;gul{Cyo%yAR5;P;kZZEh7mIu4o8hk=+4UUGZ^8s_F4P)(rzOoXtzDs&0R%hS7N*? zab^(?LYRT5U3*HMM^R;VWg0gbzZ`IgaQZZ3hIy$~iSh&Wkyx}?Z2Kgv#tvvByrM{`mG)RLN5xy+g1 zm(|updM0Wq>dm7^yp|T3ksMZ+(5@cBr?tgCEM1wql3BQmVWwKrlQ{omPv&l8CJsSS zdE^dKV>$T!7I~1T;98VG(=6YpFVvp$Rjzi6nrXQLj5K*oU}y9PT3o_D7Dgh>N8`om z6@i->!B5ski;K$ve|`be!0+)QI%*T|qW2Wf({sKC6sa|rX3TsbQ1GiUKL<;uESTwb z@>812wdCs0c4ErjP%J)92a4 z^EjRoAi|3JZO@=HV=m-S02!6<*AO<_kerM1&dnBV2_$mU#{f`o>ah{9-O@ z*@>&M_AC3Qq4_zua8t&Wqb_DVgLsaMT=_rjPsL666=8qk8AM%x`XPUWF*KncuVOAs zM`8{!tZXNAQrw^M94;`WmjX$FAB zQ{Z9Yj4L06XwSm=#!d#rQ%I&iL!9D;9T#)E5M^dY$G8Zm$78(#eBb zHB&5B6PeVbOmmmomeU)lL^0Ya74GdEJ~%F?zMnR6)hk%ZOd`K6?57Up^qYscSz6!v zB1n`|C6e6O>R|;3->LlTCbOMSRr>jCvAC95FC5_5S{>W0RFcI9$@SdtZt-io<-I7? ztpxUFy0!Ph`sN3jz5TVs1CvkWO8Jewe0Kl7xV^sFD_Nf>HwzUbbD7!==yWcfjh<}S z|E}KOJpO9tM}LyKx4WMHxBq!C$YN^pPUAoNl{c6R?3Fd{4?6bRI(GS9 z`A99+zFDB6=yS#2qbeu;pMCkQY=)4_YiHlASH62}XWz`G*K)iyuM zQ+eySep&mS082o$zfP|4@KkMd<9}1Y_AiPLoB#P*?fd^raw9!({(i3if9`+%Z&uaq zU#|WYkM8`NPpWNqBmG9YPJAPo!49qh?KgM6{IhQ!VWnK3PGs)#iH-c`o4r@X9FxAcxAUD3UtutezyAT1 zdRk7VDv3^z$~}Bs`x`&^3om-F4AbA(DbiT>jdG0D$o1b!VfTOV;hR~dzxk%HQ`^-_ z>D(j19c>Qx^T8h0z{2Xw`yc&jyF_CTyWefTmmSD$qwtNlUw!qT|H0pX^}&~3+c`Tt zJE@DfwYzzuW-rs_gOq%Jr(CL~zWi`@(-2od(IlGZ8JdbOoUy2p7>N z&;6qx@B>hxWtm5G16k!2f>WBRqVlY$kSs|sw1gtossP8SEHBFvPbsWAePABlk)TJ~ zDOHxxI~@*!FA$QVP>RMYlEl*p5#VK(6bXh!R0H@?EH(*_l_ZH^2ocRh(QJih1r_SS ziX=f097&Kg0q^bvmY`UHU?`4aNI?+krpR-Q%!#TBKiw5Zktj*zB!Pyy5WEQk_8rekrQZAmJuK$ zN(?2itV{@uNWm$H!Xm-7MQ9q^41S9K{RJ-Azi8C3XUpsG{7IWD4F)u`I!IJV6N}FG>hHn($L(mL@2MCj^0H8G@pC zc)JW8PVzi-7fA@bh)u2h`tb*iV{<8&~9}*P#HcB9V=+HG#4D7b%4=ofwlp< zen$tc0otAiC4-~Lwt(wuXx(n$bVJY%Y~N@bo+?HyKLobz22BqHzJ~(%t{Awg=5_#r zSb$)dKvvz8;KXVRwxhQD4p4RB*aFr-i#v|w_p}#)?%RGh@{~|Tqyf0N)--_<+5ldO zbX_(XRR;sMtJ`AWfR^PC!I=%D2Q=swNSfM=?Pa%8p4AaX6&=5+5^ zZ})BJpPp+(eq{GdUD5rx3xL)0)swDbS-u}Yr?jnh>_mR6)$YP~osQfFy6s1;qfj{p z&_x|!wj)~xUDNO^x$86Sv-VK{-2nt}Y$-riT1O8>R}KSB182Of=uUJ70@-Y;J`@(V z`al9&Ah)^}P=N25fp59M^90s$Z7cE|A>g#1XsDBCEEz1GXnrjE^v4kbo6#d^8q4Fa7QkPT6P$Aea~~@nY3a6j%|20HDG%1 z^~vPCSwRSl2v};zg}W}A@QeciE*J)a9<>x#@C?HXxlZ7=pvq9Q06;4Oc<_SI@;Wjc z3dgx}(+aG}^jew&k5Wq=w1bxE`9_BYzT4_|fz}($p^|@Fc>3|#QJYVLY}v+KI^{-==*;m62Pr!$+M&8bDoB8O(X2j?}+Dun4U$yc;;kx z<+c5j$SbHVfQ;LiEYtQJt1Q~GuddWomwx`G+A|3$&!OY;=Ag5&x~(h9xwm(JN;4Oy z7%h7Z9lHUj^lLW(75cdW70q;BsCBfL_L2GE?SK7?+lkD?G!FdD;Q55FAZR~(E{ z9S_6actloloPpnzps3*`Lqa7h5i_n2qe>Ny?=5jK5VlqC4acA5X!@*u)_!uk298X@ z0OnIt0nzZ!Z>bQgJLEa z0SzyT{GuCyFjL{|)LvG*Mhls##`6?6U;Aq0Qe&5NWBI9l^gKh+gzT|217QhbbN+5I z6Y(7cW}44x?n+?-In0$s_|o-+SaU1qxwo_%xE8(mJzI)eO7+Ap{6NujGRlOqan;ZP zfVxeGBX-CH#A23qPMaVus{{~4{Fq*!oDl)-N|Qq7O^_V;Ets1_L`%M09OmT?c9C0a zf_(JnA?s(h7)8$KLHWgV?H4zL&5LOABD6dSg3p50OF{Gy1*=hL`UdQA5ngc1U zAfDqNb56oF2xyV>s(&#S7Tqkj?4c^P3CuPhNyh!!&}B%JyxoZ=@-IMT&6 za>@j8=`ReNq^O$UUHy0>FP?CKu2f&qHC*YqxDqviHPB7&*9#%Y}^>|L&Uy*<6iW<6B0_e=B)rZjit6Zf_?{mYR)=?>~N|{I$Wq zEEV5M{@$U;;#30PtrRo7v6a<6INqeGVgs8|ESGA{L)Jiru|}N|CD+=`LI{v zbN6=F=z1n`vR?af`Hj-Sw=#NTYwcLavIl#$-M7E-AD8x?9`|>{I(K&u+tIeGZ(bZ= zxnj2XD-ZC4_~p{(0llM(Q3^YIZM~4lCaQ;b(@zrl&Ggphde#&V?jB})Je6-A6tdW6 zGJf>!^~`!IpGvI%R^0gEH}4a@^y~Gtdg8D22K7QO|KRQNci3N()6{N_e^R`g-`f7* z&VfC+Q^L0Hr3=Nv{j&9C7t3TmhrRaTM~`>%dII~qevc}rg7rezeXYF7nG)N z5fclIt=G(TB~gCpZG1a-@?YYEb?M^q8^2LoyLh^L@m}ia*WP)l{FMkRyq+%pQZe_E z^zMH4s8rZ_Bl}*ic~8XJPs7(AZM+gkufLKH-;S$ixx^Q@YHVR|bAP8zZdK~#7gJIB zSW8pyP`^>yQ@4_(_}#CbeCH^UPZbNb-_0kt%Xc>qz8J^4mD$Q3yLSxZ%UeGqK6sdX zrl@p6n4J0@$q*&Dv6Pq zL_PWawe`UZe~Tp_-4R;+aKlRPf8oQ?uV^3rAikgc_|INF`hGGmro9$-(PCyq_TY#-l%fSIlY{_GlA(6#W(KS0g-A?iKO$+2;FCpO6$uQY=sK z5~0A`C3VtJRvcAB)B;5nL=>`DBuSJ-l9fqSQ3PHT6j>7#Rgq;`VR;6zCFBWZf{{g8 zLLpv3CM8)!L3}}IiZq3ul~)uF#ngFsA$xuI5W>NAcRggJFWJr;eXc|hTNr|T=lIEI>IAJ2_ z2p5qF7V06ZqAGKg0vDA9f+GkP-kk6fODiaO5-F;TDk|tXewpM&ULlkTAcK-Yi88NJ zJjY2Kfl@W8DhY3tREf|ylq*S5358}PQBy$gph1fHaLf)LcetNf6-yfm;ck%_y3PHh~fZo@PWr6c}luAwpqPRnp*jnclV_K#8TG2)>E@ z$xE_A5hU3}9)t%+Ay8H>RpEIANh$EULQotl$%3RpT@*x*Xp$n2&YHlm9E(&Zn>-1( zRir57Q<-FWiV%2Ckk}^N?j|9Ml+Yx2LO>a*Lqdaa&qIH0R&?Z9gRC+JxH&Z%aZs@-)=N2Nhm^Vz@* zI$q!yfrR4IvD4|oIg!>j1K`Sr>G*+ZcWm8kn}+ANfElnSVXX6kYFkeGxb1gTM>{qR zS7}KKu$yk=sFvWk;=lu;+5)!PVFkPGsy)V#TuB2yFs(qhKufa?LjgbsVHX@bcCQ!e ztypV2T01@lLO*a7GuFKTIEvBstX>NMB?vr2x4jUwBng<^P8+yVY^o-Zb-xQb2HQ1c zvt#I%cVycjlx!J_le@GJ7!$Nwprgl7ffri90vgOK5eDj7|{KZ3)^J^iV3KcJROtf%Twmds^RZ0ku7_fgd{n zrQ7m=5=LPU1f9TEd=Q-4AaFXe<3is_E;P=yUCsjCQ^|8RAOPTLT40(!3oH%rn%@lm(SLk+`j&u(?Jpc}xYJsY%K`J`pZUDE@C=K%xmo947x z01vWoWClJ6LFl-)(lR240fwddE(gyn+|jrzL-AeJjns~(0iY?MHSocMek%eUTXscH zmb4CBu4B=`Kq9clKnXA3!p%5)ZYV*A|Kq=H zXwHP2L5^y@3MyOBBgy(DUaK&pT4gk9j7H?37FG~JW7w+Sp|q*gB+mLQH|=j zJ}Ur$fQ!KZF*HVq32_Nkt@bX*2xl1JgQW@(Q;tS&%F!4hc;NDK6fwgpQycXr!TwQw z7!9iAEVM(4Tu36IILD9W(>VH7&H*bQ5oW+X$go0Ib)0} zKupLP4ZQLhxbRu~to?gx&tPZF(h@PVr`@MvVp_ZbOfb`t^C<8%{5*pLPDEuzwO7GK~rwtgLO;k4<_Of&y3Gc?47yTrvp*PxX-9I%MLLp20y#!#4M zVA6zX%?TF4Mf7Z=X^vu=)PexBa3=x~Bxv9qO_^t8nz@9z%FV^hs!&XS&W{R`b&c}F zF4;d{iof!wc%xp(VkAA2Kl8_eyw`s%gLH%nosBqEAfA{$kg_W_^J%VbvGv{6%2FP4gRgjX_Wz{HHsu!Ndi z6(6~l_34U3a-DOtFerS+X7}eH*+Px*d{LHTDWBHGlJ!%o`wN_I3B8)@f34jl2u=Sr zOn?k@OMl#I?c~cFTrHp~x$}2^(@SOl-v5-^;IW;P%+5={{^HSxg$Mg5<-PrKVx7+6 zhd=+{tUY;kaQ8{+rKGt@Zx^?=*5lxQruka(b6Nfayt^-A*yfv=>~^XgC)dbw*)3=L z#@<2X?{2v-Uwq|{|7mUQZzP$s?XCP5 zlfp~)_!O4^p}w^p_SE=f)-uktB_Xz z2lbo3_~_l23Y4J7FaM{RWB>0RWM2E3AEh6!yC>f2WP|N6}k!+-GZ4`X%t@6V|=RZhLT zZsq@EH>}q0^M^M^`@zmPH>m%6vv{w} zX0!35kKX%V{}0@LA^m19(c7fE!jb^)i+sl-e)9vh{=ezy08dIDYZ-M5Mm6_Tc60#ZIn-70cC&@b!X} z%KXuBJzXgM%inSDXC4n;BKFs*`}I%GGdp>_mZ-J4La`kSc%sCln{Z8acmM4V(oW&G z@Jz1OFP>D1;_)f3JsP;5D-a*Yh0SlK-qDQXbfdIhD4!qh-7mOnPml8~^TYM#`~Dub z{^+>4^J4h%8;Q`ZuI2yM{qtP=TN~f2>oib=UVLIq~Gqx=}l*+}}%PGpS@IakrW;9%U10a<`OPrwXUp z!%}?%|HJK6#cIF*^ohu+nj)%{BJ(18EWO!enmohOgdm9$iqx|#ElY?*At_2z;7A4z z5Gg?t6j7#7sRmSWLFNTTkZ1|bLIoZ8X{iQuV0sBD3*sxl`kR8x_73e{RrG)dtm`Kk~$qezU%b0jK}MX?M)kQ~8@ z=qY_f{va8Flb`~WK(dOYsDeO1Rp1Q|gM$2spu&hvlI3}U;V6QKP7}}{K_mrA;0Sng z1brbPwuCIwLX&1mLEvZ#Q5aB75JcP%IR;?{Y?Bo@mLn+=x}6pXMkZt)ieP10K-h~U z(oGs+1vjQQ*qtWCjl7wp$%}Kf^Rz!K5SW1BbFUvAjrf2+vWPvY^2;#llSySrG|E*cL(XO?YcX5v(Y%G%peo!_X6E3PNp~ zs16B&K}3ll;X(|Yi)x4v&;{@ok0AwA8Uz6lB1v)RbTp~ycMla|O$y&^ax|KV7(z01 z2}dpHDdEwa0wJLqTnuxA2@@q9lMqf)CdHz79&U`hVE$VzzPhL_ics;XKj?AOKrE{?L4quU3RT7 z^ny^7!y~f|DAVlv9m_X#u@xiG$$@UQwN|sO(!J2?&@D~TLnzbqf}U{gM5fDjBq-F6Jsb5!7ZuA(_7 zCTKyuT80)Qtr6O!d7XC4w}IE~>8@&>=#&8bR*3c+Uh4+V38#6X2Gx^xjO9oIh#cT~irJBE;Ie^l+nNQ9 z+aIC-)JhM}TzJwJ&(S|Kjx9ZxjGy$Vy>|;41+6(l13sO5aRVs&OSTo4&hdyP@PQ7V zv*N>b#NvADt!21kE@x)Uj6b6+4SQzk5%Vub(s_Q$2J;N$&AaW?Oi#))9rP?r?V1Vv ztw7f8;4XhZt=DuyJriS6+VBD)+_8Qe{r5c45#L{StaHdwd zg``1FDrNMl_zWHl| zs*Q2P)`+SoJ=ImcjM|_&DVG5i8{qgQVrw+;dW0%r)KK}4DO&@owJ4ZTt=5Lnv~YwE z>zB1rgb#;9R4}6vjmi3uj4Jbr8MP>ipcA9dxEi0e&)Q$G-3Fa3Wo=qOA4_?Ys6`yR zIgKd%Lb%HKw6xB2(By?Ur7KLTP+Tp^tQ7v>uP~aq{T`M znLX5%?@(qe?n?F&_8?Bzm=awyW+`Xbf|0VAFwHZyAdN6rZzgU*Nz)1SbFi5yC zt3OKvHZ8=yz)UW#Rte8nxHd~UvZkoq+^~2lLDt2UcFT#(`it5jQ=sDpJ~tO}9fY}N zz?FpXYDcf7AX{<7q+ zaJs-@>uZH%InAzN=|r>I*j@jfe1gm;lDWNdf~X|18kV=}Rcs?$#<8y_>%wud(#`De z9tdlvnU{CWv;Bfqx+8h{99GRFA8uAsySs;}bm7kS{k&37V5!u5nXS}XW~a8^!3(s1 z;SI3uhM3jmVuswWyz^GF8l|)yrna%4%NNl1m3zqzEV)OgN_#0e(Uh8*R3=#{?`_=Q z%x!Iy3Z;$oe&YP$>6%u+n_Fjbn*Mg=yvMVm2B2g^Yd>u~omc|0q#vCaKMx@8!4t>!W1homUSIt?tq0AQRyE z?ZawTxS!j~?6ddpZs1ts^p6g|8{>}sh{Oys$2 z^U$uGwL0%Id#U?h72?D{)YM<9^qi7O;dixmqL4cLym{39;^Q|y;z|$J4_Xo7ZRd=& z7DYtgqWZ_L-P@DDyjlFf_$OccQNG7Mc{Q<-ezo|4oPB}cmh#OHc0T$_82$A|LQO^6 z^;)WRFZVM4_3U|O^UeC}>Q?dM;;v*zEU z@oF}D>76KF#P&0H!_)TQ-HUjzuJ)^RPVQp|Yk20U(%ZuD>d#vI{k2jiinMbY%O1Y} z^vQ(YAxo1g%J8K`sS2vGF?o1JB}i1PKt>LQ{2gcY}hK2DqrJtjMVh z3WG~3O|eZ5k%1)*RT9@!nNU!ID!3qtLeGlYRG_MaqKT-|^Q2a^Mrsp|0MFC1s7f@a z$W2yNQDQ3vx|S|t&@ND>mGs))6TGAfA-p(^k$Opz&; zrkiY2lx0Riw+bkO7sK;}BFH>6Q4)0))u$#1l0@_Xc>BVNlSEl69HB@kHPy5*g(^2C zs85rVpr<5KXrj8hOaLHJlxUIQ1rFuZ zf>w$w&+rJpAowOh6D%!I6vK%kE3uqNHwh8JKrD-JAf6;i1lJIK%QV6c3%URt1IzR}!O79_2{`e9 zA31K<^fYjyxNg_6faFiAD8OkH4^aIFuZ4IG8e<2b-8yoC27s-0d0^#h`{WGfDL+}b=2ZcWFL465cE#F*ApF8N4bZ< zL)i;?MGSqYcn^5GK2x!q**O0axz;TkwDa zA|1H4>B^xC;0bvs0A3B1Pz!*3q)Tzz@qp@iZ9{R#4G*^aXpLml>;%2KGb`P6Xsw3_-WaBbrfQYApj*W#>A+ zV9Huc*Gw@mfb8nN<=D0_IiTBV$%sp%834G3>~wvLcYy9%hA%R4TkrMY8^#t|k!8VS zY;&R4`G4E{w&zy1^sc_Ebyv%>E#J1ctd`XG`@LJ2ZppU1&pu~PGMmf=m`Oq|lT4*x z7)UBbWd$2U2~t22E(H_?c_42T@Rp)NajD8{Uic4q;DJAY=df1GvL#vG+h;P5=c^gp z>Ry*`eQWLG_V?@G_ZvpQ59R?p`q6N#r2Z8=w!S(VjwVhJSfjZf$Fb_ZgPRmiVt7VY zu*TcgkAD2k|J(Qqu!j3m!J|Cq96siCgKg#Pjhys)viRllOPd4e8$WMU40^7Sfs*g9 z!BJjgtK4|B^z~UD{%K`--KLMRP=e=K?@wa^y9p59YZ|TDM(+P9{?8NtTOi14d+d*j zo4cRT(b$5Eej+A{{_3NW+iR#C?k7nqOE4!|&JRDnf@6f5JcBU)(hhFO`&UC4t{Gb2 z_YB)Z+ztU_AcjzEHb1wJ{J%xWZs?&aEY@Pf?rzA3*kY#W0Bo) zw?bQ(-L`XLNITc=5QMCaup8*g?4G|(Tl{V3{vsFe;BQ;a83!A8g!z5@?k>yOArIt` zdxZLM_ls=B4S}&+3U?sF33tbHUki79ZC~3@&9)Ja!5R?pqF}f9m>ABwVVr7OHV2K4RL9yw@R=}kI2eePJZV!YeklKaQ!va=? znjXp{J@PCxNmzOP&_R3@|9*sB)|n%#csxi==LmrCBp|YCgq+*NNtPWquJP+1w$Tr9 zIrD0^rMs(2R^sDGYk_(eg>{pVN;~YeUi)j)LDgE{{56-hWxiEweJjM()C0*<;U``l z^apv=rS67m$;$WLD1`NZMJy>P>Z3l#x;+cwX3QS&k>}#-TPCcAP%P<*Kl6!BYpu}u zIqWfAqffkuLp;5wpFU=spAy3#(T0BDFnqB}C|^IwUOeXhuh$C@T|XwNKdgZRn+fNg zGpw3jKfwsk3r{^I+1JDy@}^G`5)Y$12w!Y>Sa)}wHt+}_Jkc8RT3VaLmPZ)ni>;13 zWFfX)UcdQNX6lj5v2^nB)~;e&yX*mlSaa%n3u9T^hE1-2(g4e8?@w zRX(hbxy9qya_;fYhXBi`?-5h-vt#+5Jz@^v4>ZHJYtvu1zO{#a`^MrAIX(H=f3G%<#1rR38?POF z#}9wy2gTpi-?9JgEnR1^OP=_f-#nWZ=sTR~)Ue70_xse|__yxbhyRM^>2DSBe-i)j z+@Z*~MVhEcH@MtjzHlzTU~i6@fAMF3@}4|b%Z2YB)+&{~2KG*O8z`|``Hrc=Mh7^1w_DE}X!&ov4h)y66&JNu0qdq`B%pvzGHUZwGi z&AlS_X7aXF*q07VB>a=B(S6^*%2mBy*gq&^-&UAzg(Z%T@Yd-sRoSD$tgih$$DDlo z=k~GRq3H6#RcY@(U`4Kgx2MGtQ#vCW_$gVbVt)g}%C)ym3O_8<%@d_u>2_G+0Her8 zfwEfiAD;Y2^E2k3vJ{3_-zbeQM~8p-%kO_!D!wBM^Aes z`A&;%;6xiMo)8_eV-b6WW4e7w7ti$=`-L$3xBI2@8Flex;i#d8`rAYM44ZuS-~7zw z;Jcrh^7{hTNdFo(tNuFu+s(t$Q5goZRXt|H>XB0XtVA#*juonfJ>RYo`(EL!HL480 z@w;zo<$v^@-@ypV{dtx|e|&zcNV3>@ji~gg@_D7uI_);~?i+$G?w|K*x+G&nfhr8@ z1kTVswnk!>zmLz}|nrC#8p-8MjQbe7(pbM>ivUvP=30x0q|L&K6?TDzJFc{*8^!vIl zo0e*dh9UL)65lmV1eX}*Kv^kg>ykOpOkGuw1eVYhd!m7arWHfbbxG3mbiAPtEOP*R z$VduAH7(uHklcaDtGxkAn)hYII2ma0I#QfQloMUdr7nzIzyoEad8ym&OQ>d)((Uqc z56OY+8m}YrgAAX%R8ipvk}hkShV(qTqOO^SY$cq3k2eerX^#wy zo+vAD+q!*TQx&vfGLkxh-Wt8Uf|;b|PiBbLVHu(ZCx-#n>5229XHwP=9rS%6(uBN-pe1w;1Lj1!|1^ak~PTdp=q{`kUUdCoy@MK z+R$A~R%`?enmR&~4Ac%amXMUaiE6)@rfk~-!!{)m0ZR{}HAod*>2qYm$KcN0#betBaR>tc+8M@|eiqDNd)ETtW&GJNoPc5Eq`ol(=`fm%NBSfU ztr*cghMr*rVlWN>{3x4ajKiUthBsO~ zazZx@=l;lZCb|l&J{)NToG=jGOJ@u+r2FAR7sqaL9l-BlW`mhO%uEoulPDUyQ5whZ zLlD{iFbe%BL(15Z34o-*6_34f1g?Pzg8_oXAIIQYNJb_Yh9LETqpGIMtKtouG4`D} z9U@1E?|`4iGg(H}$HHj@!qj%ad*3mqCYTI|iJM&xeJ4^~01|8LgTx)X&Je^r@Zd^^ zGs&5lSHnpHz#y>z_f{pzV+-@a} zM`knwsc!*irX!8;iJ=ED>PhTGV0<--;GV#E#4+%#iD`SG=Yb@(lUa2?k}MD7^_C(3}~nDDe3app#e<6Fsi9M9fIs5+Mk z^qwI&F5I8tFqqx|ZR7`mt(bnCxG+L)qz_{-@ibt-p>;I@4m=g3Vdgo02tp5TTB11P zV33F_DCM6W{^-ZwoVPv+rF=y}^G*9?-uz|dh+UHpcDMS7eNwghIY_WO!@g>_gOjjH z-B{YIDn-4*oY%>gKeuQd!!R~L9_Qnwu0F=w@Hg7H&Mx%mqX*_==uy5`+bGCOpxBFH zdAP9#uslFLYa_1>8oli9F8oN?2`W8+S;jW1lZPpf*)x3QKkuN3xUa@nJR>l^?}dh$ zQ$+65MJsEyn%s=P=k7A@u6fTbl{{7)5kz-b3VGZ&TYNjc%_$C~{dfT~8kzhwF zLwXw*-2ArPN$)#NqzQruBB;vOiXd_;w7E``Yj%*FM^oT=G}T>eCFddB^6)Ye^T={B zk0x^KuHCt4&+q4*RJcd%kmh}c1l5HlJ0#cg$Wrc}o6qj<+bI(BfM3_dJh;w`zg?<% zAbv>ue#H+-+wD#+=8M_KoDT_`=WI8E5&$J4;(n)GH6Sg-@_XHj?ZwrNm#6^?pw6 zSoyTc5qafs%W7XQqEE|_U$#}pCrOeum5KhA7ayJFC$ksIlF8z-pw-I|%u~ltc=bGn zJL2(CsAqH9r!rexpxUEo`u3#avo>3{adnrHN`G|?!6fS?tFE6@AU3kiE4zN_2D0Zb z*6+CU{KBfj)`ypK(`$vdc2Dr~Ogjd9p-sAjkMWA(mf84^rqw?-%JtUw^`WK@9jDuk ze~R{!%E@#CHP~V6b;3Ss&xhCnT)cW^YY5afu(K}xzM%oKi){3=L(3*xc;Kp8j)$P9 z@JdY5_ytq`f{<&M<^4|Uus|_YrqCb?)q0_hkrdrH9u)V9dWCLyRlI=XI72onIDbf$ z8btX`sfg8iLOtWKLKUNNjA?UtrAU&+M(v0qn`DhH(rv7XlO&B1Btzf@jH;Pu7{wo! zF!rcbp!n0jykDqQK0BcgmAXo{4(g=?ianwB$Pz)}9MJ%#d86PgHP>z$;|? zq*x^A-g~T1SF2PFXN!2PN|4wASM5;sw;ilD`)Yr1(sn5jG~)$ z?BJXzRq-luT$&LyQN>c|0Y)4#4q0oIE9VT|VD?LWf~sQshu@(nVh_WLvc=E`XT@6a zs$SP9xDWMC6KANsVyRa89&xf?qzWabSzsyltX@<1PL5`U8df|k7gYSLS;4R$@bn&e z%q2yV!>Tlf^$+l~(piCG1&q{)Q~IQi6J)DZ$8oxNR!ECf^UeM-cZ2Oy=X=GYDuZJf zOR$w%n=gP3429K-Rkl)TUeKo# zj47AuWTV}u-?ZpLv$=OxEAL}uy-?-~RGB`i9*|wBxW^Rv!!pa0biGEG*@Md4661~N zdc&gkYh`wiuHnKS{$Cm-sWX)}RUl5;vR>TZ<9NJbR_V{`Y+)b6jRr+iy>_d}VwX5o zE0>8DLDaB9v4BPA1(q(5ELA0$^rA`P1VhtInfd-f>6mc|2D=-4yB-(I7}IH(V}`37 zl!!J-)tFkV0r%pdNaoBCggK~vL}Jj;tMc~pSCb%Fifs=RlrlF}-9i~)+eWJ6=v{ir zUbeJR#@jG#S=V}o-7`!DwooPXriodd=RFySfGE z?k#DO=0JxZjlQkhRxYZh@B>lknyA_q^u;hu8`Uf_BsfN2Fb&g|m--yAxrDy*wk08P z5KE9%9?=>U%RotO1qqt;WJR?4u!EWVfqo;KW*3eLgTTu??Ab-xe@&AHilNF1(j&1{ zQ&6DKsx8?zT&bNe3r0mYRc&An1XD6JnOFOQ1nYM#_rQAY#D8mW#Lf@+)He0@kO z1&)I-5(9w-MqeBlya9tR8){F7*DVRP;8Afg)mmz+=jX*hYqo4b5@1}HAd6+H@JQIu zAs9#tagJ;i?hGF#N(iGdAm8=*w-0_>50wTuBgbZ|oGV9qjvw-vEF z5D@lbX|jn*mdWsgC2R0->H_=>gDVV7^bDt2Fj@l*h8;bBAqWHR9}l-3fqQm7vkgyi z-+(?@aQ_u}uF&a%dym3{76b#-GqoN%*6^639W&w09N~y;cb-JR)!aCk+No-oS5cVQ z0NljR7=TbV{Q>Z#G%~_*G)dC23tSIrg->+Pwuf`op2Q*0KUX}nJuZXFvnlCCX?5kjyS8Auz^SV#S|XZRx$>ObvYi5 zKoDk8a0P-(Uu8+BQVr~7a&y(=oD}hb7BF+2pPNZ*iFE2_|6SNKg)n^0_{cxku{h(S7AI>X90j? z#hM4h=SFc5PBb4jy1DXTcXcL!=o)%qIm1|kad|f!TXt$iQk+@9ga20Mp$kkchybu% z%TK0>nMR{wENbIWv!_uuOo3~I8A7SlAho?I@J7Icog$E4=)eJ}Y}HWqQqvpS*=3yi z+R$+kJ15qGf1Sjt=4Wou_jPUPd6UpdLNGEXVCFz~YzG*2I2yx!oCF}SH5E*Z(Qv59 z;n4DCz7zN1}Z>xe2nwPRBN? zl!qi-Jll#y&y}yhcx=lvkj4=(!^trArbCdXaW=fl;J$#tcxI;#QdI}DAen;MC`Eux zgoN4Su@jAxu{Lu2ID>mK8hkc{J`aI59)=<8tqx59-UY!Zm>7=X!S$)OcNGH|hfr~n zAWE<1NtldgredNk1+ED~kOm1zbkEP6*+f}E8UOG2M?e1N|2X`r#jbXl`;b5W1U+EY zc+EZmb!^w4+6@rAve433!335=ZXhQwf+B0V@LdI#UR?(2C3xX6MjIuyUbUJv*Ve+m z<>gaQRn#N=3bc(^ZTO$hUItwrL4^%skoq!rgMZzOKhYuUuYP!jS$w{O6Y}o$m__K= z-}n8%#csJ2VF$MhRA-5AbBkuq2+0s5ghNsxJl}j$3Rwsj4^knE45j}&^ZDXp(ODoN zas(nEQV7p?+L*~o zkh>OKMwULvg$UeThZBUaDIs6m*Y;Df-D)A?GEuyl%ErUSOVMWPahs21??vSOrw9z&_SAj{ZDuL^@i6&T^ZcSb81$8uu)Kv9vEsHo#!Yxo z+}K1S@-kUVj?XS9%6P95@eh@Zwy$sZd8)^>NeX!6GE6ty0CYf$zwI1k!__UR ziFI*}C+&>QR+}7$)gMGDwHS;l{_-o>j#mu#!}d9lJe3_-v7 z;-d9e$%0fPSe3v}*gXt8DHiEdc2@M8cuSG3S&^ty zFg#_kREmQ`?5x$tk0gf1Yb=JJv}+Val8iyq#XlG{OKi-AWn%x$1%(YT@?GT^t_&|S zWTi>Hv05GejKErC?QMZRI%ym-6uH+Z4jPA)+@*;!fivX>aab$(WTC;7m@)=efK`q- zlBVIta1?d$_RVQ+pEx>VtLza)AN|1F=UW&3O6`~<_kOnUrt}WOX|B#<7maH5j3o%N zdfcwr99_D^FlMh;DgG8+s1$1?YZQw6HR9;qIYAbVm@!o(&I(j%)@M7IPGTh1DSm5T z`<$y!iZV$TJAbQOnL9+G#X(0dup&Z4(Bqkz=Y-Xst|$W$Wrc;D!JukAqz7i`hHY4~ zsc43#Ac1k)7G+dV3soG-VF=hCHqww>IjXOTQsainBUKCd+uqE<1Q})04MpuK270$1 z{f_U+NFQ656&;l<(g!&zV;R;!5e?Z?QF7jvOu@2w)8bKHJkQ1(x~dx@sv@e$rl$1s z*ZQSA!>ypoU5cz5Ic{R>s-&T!NoL>b^<@L`G7Q+G0Wf$#ni-sou|(=R8DNbD|s?q zGAv%{TAFOhTK*ac!dFo7CVpV(3aamg#M&)WM@WDrbx|2EIDF0@Q6clqg)Wk{fy;*H4#rM3;c+*6vSur&v&QEk(5!sN&|yG9 zg=a+;bN?)}Cs_z40bn>BO-J!4u>f$c-i<@xnj?@!kru{DGz|erqa;c%(L3{_cR_4{ zu`zUGl!40Tfn_G<7zBZn+R+4Lv6fjAYZ|AcQ3RyX7hsb5Nub1mKLWlpcEAvTKy`tc zBC>$!&3r2yf-F%#12*4_z3B4l<}wW7T%Hp;ZlVc2gh-?*7*Ep7j)E|pOnf&1G4Q+z zaI7R7hl&@5j^zvU@pWbf0dRc_UQ$gk87ISdnE1dpfB~=1V-Ey^8bL1<*A9UQf+(<4 zdo-4Mj$x-D%<>{nE---QfnkzNCw)baMrj%WHJaM9Ftj2N&jND@+;<_kPQq*qE+?7^ zfH4`3(*z7-e~fU4*t0Cej1htB*edYC)N}1v1ETUi@c^*rK(kfXOS0H}H_;L>`%D7B zSIiJ3+9(=cUtWRfCAhRrcj!lQWCK4_{oc?Y1wkARlgY?*1KSy20T6<4Jl99pGZ$%| zBts(sz8{$|NaIM%B9O)~Cc$u=M2Q)Uk`dg|AO+UtJa&CI8)@Mzg8hJZX?uu&k=d7a zG9G%NHL~MT0Qzy{jK}Uc^|GlQ##09_b(lFpDBq0iE2QIbgXkad@Pu}nO~*bw5Vn1N zli@I|AImaex;EAWS^p^@2GVB%$pNtt4`- zaco_p`dyYewld8|f+ra~=3{3P`H?k?oD{~)nfL%6;9(H!BNOm&OdGZ{K^jbk@IX3# z97LWy45A@;4=!iH$aUQS+)P2>d#M1Dc!iz(+M6H!_?zb^pTgIDImM|Dv`8 z9QHK?6Mqvvd6vO`dHmh>j8*WIo9`|C$=L$IV+Q?c{+AggpWvFT`)IsU;A7q5hJo6fMh_i@_*E}Z9=HtZ2|c^ydQ$B%<;9E4raO}>I%QC`D2KDwC4ZI8E3U6|}# z(#Bk0sRr273H6__uAg#|EkCfr?+2cb1lU`P77_~Sv|7y>&)sG1j*y~yS+fhSvqy=&z(kmoFrTW*2a8%Uvp%eVzM zLo|^4i$!`bG&{mQYzD{UVB7gUpLOnqyY{TzY`5Bc3yw5{c9AQEAR@>ebmP9oqncS4 zX*%QEEg_v{+%5EvOE21UBoxv_^}<@62ceMLwB2bn7tN(m$i+R^L0Ax+vy-+3L_fJ- z%!E#w-QRcGGfsftkyOY9ck#dmLDZC6uAR2-=R*1<7jk=l2UmpjLY91x_Wecs0*0uw zXm#4{`xdI~b$i!D9p~wqWC#+HM_Mb*&TV_1-rY43l-1;g1yT%wV=Wa!keED-CBkv$ zUn44C+t>EfvYnWUJm?Qr8ERzPFv#Nz@<>tpSqlAQCaitkw&&UO=L!4g_IPy*W|8~K zT7xwQpTjZIBM)N}L0QV9|V$tL?Zc=Oe3+p7ghFZq5E0 z8$285x%HkML~$EIT1NZ{Rk{AKLPMrI)6q}w(x)qR?pNB5GE!UjUcRzBDZU|mz3yYW zj+8tHcQyyUex_gY#R@-4pDTVmifTORnm=i0Jlxtw4>l+Kh!D#9?8_@39`UGMq>E?Z z*46?)Y~6iMg!t6%?F#&dkF-eF=2^e{3fj$bhaINdv8O9i5K3g<6fwCGZs7T8*?#T8oZGhC9X z5?;m_=4jGuA5j;_&HV~?mXge%Q6|rOdlcF9=7k!4O7rJ?=Tx2P9Di$6DwWUoNrHMq z?p+fMyLYyC+NkW~g;MpfB;$3OZqTQAXOGP=ntK=j<3FYdtn-EsM|6;LPEs-}ES*D2+S3Rl`oqB<$uqIYIz{otxn6yA_{ zdk@>E4#@h^9$D|uRN|lV=P@dq)(44CnQDUaKQvoVH;F!{}8KQ(1kKQUl?^*rSVFyi4TbV za|}B^CoV{gW$;?NdCC&K@=^0Q*t6;pc8p^d>5-Lj_wuY#<1#MktLc`m&MC_ zEKOth9!3|)64xxzWeSha8IEAM3Umx^Vf!2tzkBMJ>*X#{BFaV5#2R>wF2YlGrcwKQ z4SZ0b39MA2zNpI#N7aafw^9br5KCd4htpN=nB?G*-m6?v)ILG)Q;lEy(RaH&qpR`4 zK>Wi zqW4gmU*}C(%83YFt8W?x0!C0TX<6{evQZUPyWh1`LqQk;(jgHPYtU6p6FsMxJbI4@ zRs7NrLjkF%sVHBMG(cptXCUeU0z0&B-_%5;P;P0GiX^iUxkI&4FF2r%GT%LOU@KNv zRCHBVb>y{X_9WBntClJ0xjYDxOECr2G`hMb4Z6C)8?q@HIt&EL{@W&E{`OHRG5BO+ zBRqh&L_;2^T~(92ydVgJeh=Xgwxq~;C8ivT$r%nZ-_rO* zLJwcaYq)$2qw~0 z0Wp~n$;g&u)6fJ%&AB29!j-gvrRk`=Eu0aaKdUQiaNP((gzbec63sEuF;X-Wjbm9$ zx{L1BR=Pf|+lEES$Q*&;{>e5Jp}S2KFpUrx5`D7`TC@hu#>(v&j|jt}pn3XHOLXBrAxG$O~;TojBoDnu5#E29D;rfrFIT;W@DMaRlIh9s$D3 z0@Ly03;|LzU-Nu0jmKNdSg$^;08*4gq@{MCv4TL3-)h{&kSufFzAP z&`&0w6S`N?aFU;{$&Ig%V-FROgMLfFFv?Ufa?A+;}AAj?o zzxgRJQ?^i&m&zioQw9*{BTt$4P%i$(^#68V`!Si`PhMxrSJC?ZiOk-adp94ae|BfZ zk9b_P@eCN)wYu%7K6HO6^S|AE8$o#Z>@OWy+N*dbpAz}_G-UI#1=~MAfhX&*+V*kz zbCrQhw)ju+GXb161Sk5$gwJrLyaV$68NTxW0UG#xNy+#C03VA81ONa4009360763o z0N`Nky<3kf*_t4<;vV69L`G&t-uB+M!;bsicKDj<2s<-fRp->1?z0awT|#r1o~EVK zqKB?NErDjFHDk*o84W@R!PB(FBaFlY2qYfofma@p5D)wS#7{t?`IhsZ>CD{wbdMTP ztzG2|N38YTS2)&pS@C~q2>sP<)BkFrAjF~z=HVQI_NTp07IiGLLJk!->rmY+DMw@R|E4?9S znrUuwZL?f17Mqp1($<=`nyYGEtHbE}62PtJS}t!kOTDq)Y}U}*)D=xu<>jirTI!ls z&l<|6zFFm(EU%QhvRVMfrL3q8b+f9k>*{Kq<@Ne{LCDzD=kxg@-{hNYDQ{NlLf+^r zwXu*F=2|lw8^tuU%_av1)OD@`qWNaMSuB_9MLk~vYE#d&T;1qqLtSsO)mmH1<~m<1 zxo$4=#%f_|3m^n~Z*m=|UIE4HMW!vxmAsg%_2o*oJ35-`S#NjH&oa=x<2po1wGIo{lyR8zt*nrk3Pfy*~7VPdn$W%;O)rIkIrOIFFn8f zsD1u^_B!AjNY{^`JjJ=={F{*e8tto4ePR22E0xbT(05Dd`ssk{hr<^=@2-6Xr`dMQ z42E3a>iunX>>_XW{UaSdk<;ue$oc&F$?&)2{Qz(mvDx*rv0p;P`|7x zx`uSo;44&tJEK`v{7|r9#lY5BL8K1Va+P8BJ-Ys(BYZ@HcqU0QE&ONl?=uW7@<-L9 zLZwtLvy3Ajv`@}BCZp-IBf7`Y(jH|vyj(=V;WykFrTiXE6?nSB7mE9mT%(WK;}4V} z=``9e9G8v|O>t~l{Xo%&1G`jZC3MX2R7q@=B(K6$dG=GaK$X~vT#$H1W)2F7<3F=J z$1q}bzk`Iz-~^$9#q#vW0(DRp80zm)#s?Zz4hsyDWU=sp6IiWSV8m_}3I9~24>%ST zghp8^u!vG?HAdzSME@k==ue^`vEPY@{Fzj6SZ;_AUDFs!Wt!~I_e6b4g43m45a;Qxz$y zRN%77r@>A5N))gyeFO z=4r8TN=YRiY~lk=(Vz@k6&$XP_>Y#jR}t&<87dTc^>AMk&W4nD1hPLYaa8#fw24X$ zsZcJ+G>vHFl*%VGN1*~;J}I%Hc#0VIWXve==bxUk(kJ7f${?z=SEzN_8WNSgQ=w2j zWm&(wUo4`Gq^_(D;^2FvhPVHn!O4OG))k&^d2RAXs=wMKdOc# zI?4gV9I+o|i7PkcJ&Kl3_PJBKz!p&E2dKomhLA!?+l5l0SX|R|EKOix3_(2vEy0V;JovHo2CBKy4C7v2WT0 z6bu3RBu)a46HRCP2-~zn+m1pY3&46FfM_-&fN1!(XAhs=dEQ=hQNH7k4Hw5ei!VnmCVPK1lje{s~L&pbl{5bL9pJ^wcVAlg?;u~3naXV@`0elD4QLOus z(`vf9?^#g@()7)s>4qi{3#7P)39x{)#I<}v8fdCbWF8P90!px(xCunH>!Gof_qWse|L$8BRs|!`(50{bKL1(IruzDJMP738U}derEqzKqoiYI zi#YGkvx^?ihT|0D$q1jHe}C!Wa~!ArX%cm_3%G>C3p|~qopX$@&#{4%Q6Hzn=p4_j zY}~VkX*kGZ+zG!K4F?#YU*_;RJC7~^Q9m8^&O1FE;BK09@kIv*X~*mJhvB?8N^sH( zM(KrxlgnfbSJOGhxz(TIVYk;m9}S~Hdj3s>&pWwe_mUis#)Am=VBUAb=)$^8JLAa( z^umMgpo81)_-c5L&nH0IxYx2q*ESrQ z{Xyh;*>HFsfzZ-nlKA890AEde3Bc`RJeZtMaqk=t#$e_^%K#59;x2F>;&D2|qh!#T z|9m((KOan^XcmOt9QWtL{$%V=M!jhoj7K;g0`_#)nT6w7H|pSSlH$prH^TjH=ej%f zM>xFBa375HXCo^Gy`__@7>D2DK|014qcjH@bV1vLL1&yK8PF1TA{@^9MtXULFRwv& zIbKX~7EQ+&-eiECeiF}zc@H?m7xU40I!H*LtOttgsp zU0q^445nd(J?voI$CHcp5MK;2j$@pTeLP#74=;x)sAMt*0iXBdg`ZsvCJvsB^W;2< z`uPydb9~jgCITMJuCO=4Lojt?(jWALad*_iGaz(2pMYSocRn6^*%Ykqx`(4K7=L?u zJ@Ip#&BAZz_Za+_$gg<))=?ULC%E>1}k|f&R0T=8lftM+e;<*FjA2 z+{|1`(RlRq~^FfeLjG*^Ar%wTfPtTx#{HMRPgn#%S&X_;{ z@sIzT(;qH=@hJS!x($DrUmX4z^up-ZQP>FwNX{0Uxwf3wvn*HhOw;RH-OTdkvOcdX z+FIRco0Xc?>vCOftk$Zo$}2crXDe-`Z@;Y1Am)R^-V)n)m+w8b0O#Tp4&X1T57oTgjQZROV);16{Jb zS+3+<&Q-X+tk>6@xmnN5bzPgw=G6$(3a?^H2 z7hW7)zaZ^*3X)_yNxy!Twp|#1r`XQx)V_MnC=t{;?t!ggx$v-T&sWBAhVn9$S@Mv|lOG zVX49~3dd9qO6ZTJ;z6}c*Cg(wR%R+(p~j#g5(S>4^oDf6BdN%pei9{{=P9Hz79Xl* z?LcOWLQ&#qv0ObVa!6!D!lp)OwWdvcNE zYqhhzLSZJAWcpCz_N4tXHK;QRt*OPP{R_JEQK1g16^dhxeP)lf8wWz=$gT?2lEpK8 z0ezBMhjK+$xe6!J+$pV|aH5Zd+8JOxW2kDi#L|MGsYp!=1}O#U9PlG$Sw) zhd_L+rqLjSQTYNCet66vnmal&3N(8}P#}t977XfIQb~o*2&vVAgh-HQzs!CppBE0P zy?;+Uv}h21$zZ3dNHGFiL*-GGrfX%Y%vU7t^ByCJG?KVqA-TpI)pDtD$WWKJBo&&RL6yW3&7M(0u}sr+sZ>`;T!Q?_L@x0zhq0r(u@|<& zsF}ElpCoRaBvIm+#CcBq$*~)?BiC|?4?iKUVkac7c}pi=;B8#Nw>-!2J!=~XAl~yZ zvEj%jv51JcoMS%;1CO}G;dEfax2P2ce&8j^HiD4A&tc^Io@YfQnqYV>ck48_LeI3K z#A-Pa^zey`Kej_J(j(u9+Qdnn#E~7@j^X)c6HY{gMmLIrK(`H#5J!CKNf48WKokav z>yd|)q?N>8LQul7?}Skh5l6m7&LspyNJ0*QPsoL5mB<4*K%dAXWQH)bX%pet0mv=Z zfhIjRd?zA;0~|4lFeG8(5tnyFf*4*90y~N87J?qBJzKs@nfew@z4ve#dW=P!ZTe(HHZ~G>UYqtn-2@z!C8U(GQ6Q}!4S`ZKr zfSgFk1T+_fK)(}iUHk9>@(SZ1X~#a$1QmZrfBtZ?|Cy!-GK-30CWF{m4(V2~sSw9=} z2I+K;aTsJ%JQ(5;o(zT)Gs{MPw~Osygt3pu9rzfg827u=^EkwdE>4pfjKXQpO9!2_ z?~Vtt(fMZPUtIPF@ntudr2Waf6Gz{4dw4j+4xV_?6vxxV=%m-tIrc~Cpk?E6Hb?_J zNWyM{lR-ZoO#7KT8Fq$%Y8duLaA5g39b}le;3qR2hTX*gPq2&g6o|#+K`%d_;NkV~ zJnv$_lU!V!kH${=?d1qZ*dFx<-y}bq&u91=C*4tceVL>f23(JEI=V=_K@@lU-}qOZ zDW0W+bdcalKb~}*xbOGyx03-L%|?AZyXuYOUX=Rja5x&r(_YsP@GR-z@%b1}ae_NR z1lXoH8%-v9e>NWW;=Gq;{WKd#(`k&m(eQFIJokqnGbitK&&RV1AV2A*xEtV3(vSLs zv^%ow3yiHa$~qW#aNPP1jA$~R_(SL70%v&A9S|K|z`q2?VVVyoy>J?jgB*`81{g0c z#=VR4Zuc@8f@Y##gvV(o!h=!L@67O^GnkA(+qgHivr!0?eACbSgWh>B0GQwQ`y<=~ zA&1{u{mIzI`08TX2a#P)FJ0o|{w^L4rh~z}gGbk+@eJThu|G^^LI0xTUrg|5GU(#u z3JC0j&0K>_qV5pGx&9mvqFFfX_lUwK>99MR`rRoU;TU($dz}gN8BTlYZ~%fz#={6m z8%}}1{&hCDy3bbS76R~jJxUJ9K_l(z$&`-826&iI2?IV zo~FIj$Vb-5!#!uzzZ%5`HWpJn&Zp6|KgmbKBuRTX>-8|`t`kLR;*5vm-uS%V$0K`i zfm8VJF4FL?%pZUI%Vq1mNW&W~e&*!<-8}4n-S&W$L=5iz^*ems|7P0gIT`n~><~zF z7x4I-Y=fs?w{CKx_H_Knqi(-GzWWl!-&k{h*MWb7V%izn7(P1+cXfK+9y$#lg}7dX z6xgGO@Im`Fq%i&BkU|u8y6Las$Fn~`ikvmp@;cw#6jf~GrFmOZv0TflzF5t5C0nSZ zLPD0;i_L1?$ccyFY;4x`%|ffoi^Zm~Ax`v7Bg=BFu4$Q;uQ&5-O{yw38zsLjt5{`q zd6UW6LtVv2sprotE9!F+CCE(`F68pUyeX~7)*7HT7i&${HXGZkhH7f-#>&()d0k(d^~EAvE!WyoHQ}q0=M7TvvD#?B%qAldf}6Su=(gOJ zRS>4;^{fFP*0)s^^Tz6NS;Z>bG=RE!gOpXQ7OI}FFjk+Lsnp#J9fa_7k73 z`>s3pxy#&sIN>~TP`?-6i0>Txzk310b6Sk2U#xhWU*$ZYx;ZkQ^xJ{Hy_LulZtO>A zcKYF;W%2J~>Si^!YjFHL>~h=gI^O~}Ud8@Jw7jIr-Enk7iSro!OZcRF`w7%ns~BDY zv7dKt@3w$jlFS`Y+}$yl=j~37?}d3h>v0j$6XM>is`&oaF`PYd?0$aNSN{BR_TXO5 zUUlHV3F~$L^n2~Ollt@1i?i>qv+p0+yzlfhBC~_e&$9>W9{2kE>WCM#?CSIRwF@t> zJ%^G#>hlFrmuC{ae)jhz{3q8QLP4+7`Vh3aL-wi`UjTU#8~D82-~A1cyQbQxr-_Eg#dUP!4)%Ko#XZK~u$!#7Tz-vT#VDsxDA;k!SZC zRbD-15K}2J`v+_R6?sl9G%rw<6-DX{SxAx)TPwB16G~Oj_7AxtZ&WCOV+F3Il}|W? zPX9HMe#sy5Op}s}$N%_0_@Dlyn4vQBmpnoj0WAn;ii8Bw`+5Bc@nz$LV(nUq6aGRh zN-U>;_<)KOC9-T)tn`_(Of_gJL1!!~o-rqMRoUM!u(L8^y^~_{tEfa3nZ2m`t9|N3 zMa+Rv`gaVurumZiq0&I8DwI{AN2jV9cf_1>Zd0aNmaecLYT`ak75XB@L_EzGOZ+}6 z)C&ATiPl7ZpROU{BdXOXvsADSqjK@z7uyCS(WhF8{y0bDJ*ik?E~#URG+{hR`j1>Uh$1TrTg3BB zN)w3N9J;rIz#t_SkxgnNe9tx8&Ng)6MuDpnh>_=PLn9F>@C;iw{&s+A`VlET*!~Cy z&?~fD$MWr_P6|I-e(Zz*#j;J3({DtM0f=qiattqO24U>DaVsLO`Pho!fhKaTz$ae+ zm=poD?a%_@=uzZsgE)bHQ^@PM0em*~sO9SBO?)Q~lQ4|J&}un8401e>$Cf-R4*ifM z?gMLZl>`K~7@Pi0=wKTv2!Xby9|UbT1Rg@&26`O}o=99G0CF{S^|%?5nhM`>6ClqZ zr6EM9(Ke>h1QJ@F9XI1Jh(X*5i4q0&wj3rPf^0`E@^s_aBqEiNs6s2YLlW`;RklHd zUdtnuBViPQZrVVdlbED$Kmr5AX5a~_P1uUTPyj#_xgZBUaO@z`?UN2C zgKcyn(Mddkh=5d3M4op;fe)f4yn|qx@Lc6=pC=QGfG4qsAn@Cv7X+qH3OC}!ivz=R zb;Bn70q^aQ1g;!Cv=ZRL0Xcza-I&DRzYT*DmUi|=rP(+p?lBRs%;9S0uncf&sJoKG)s|7tKDT@7aV zA{=!m-F~M(z@vUYJHHsDBitKcj6qrbPI?&)I)hPvJiskH&T$vxF;36ZUJEDbXfm88 z9X!Q@&d9@gf7l5V7}y<*yP-Fq<32t=A70=N?#F}fY`?MM}jiFet;)^AfS&&KOgwt^oOH7?5ERY z5-ohIm*8HE(;)BnCMm|FECKj^9Hhfe$4{=Ooe3#}2oq8!fXA7S$HUniXBTlY8UzU* z4aWmgJK`tPWIhaWU}AraqiBSOJ?xFs@ET+?z~l5==+qei87aQN_R_Aa`kZZa5VowP+nH|)mo7}9w$t(Oe29lvF@_O? zJ_(LooyQaVMR}I1fO{aX522TT^jK?_7 z=Y24tac2;8akRhzh`Ue1Nq%pHN8KER1BTU~OnrQn_GjHooDPPA;SgWqZ~NykIs0Iq zm)W3$FM3H2cNTVb5l*}Dc+xkz!#>F2VjA}b!}9>+JnXcA;jjZb>i6*UF5YqE{`lKp z{%_{{@s2k<<&dsr$?$I%bKJETr3|n7{2yO< z6vIg0<8RydjhcuTExutrdWv=nCVATPy*h#ik{{v!q7s4I_GY}{7SNj&C%dCxv3m=A zXYt0XtwlcGEXjDg`sLO3MPZIFgWtOOvlZM{TQA}u%ks-O$p1)vaU2Am#QMLEqBKo! zYb(~doMrX7F0XQVrL5&`ZAF8W2rQN)?4T$z{FkrRikfE`sdHFlOKsIyEcK1NAz_qk zl`nPqro5s~plS77m9x6pAk`J}TFYhVcvoGqS~u3(YE@rswgna>YEYL|SzGH1fT56R z#Z8fguFmWETqhmWjl8U9cO@38sjYNUW3kNFYOZMt8MV^QTvt|kPHH*o)4v_h>rd^k z*`B$sAGxLNx17Z9I7HhoI=${Ye1zrJ;rP^b__}ZWj@So0U$(i-W4Mobbj{WmjM%#0 zjkbM*YnPjIN51wBPwf+l+!Joxe6b$Rna0z>?hd^WkLl;fo}hO(mwD&%<4&)`dg_2B z?WvRRbyUwBgx`OiH}%n8I(L{pzdio$YL>x&xBlK;eC;^5P!`xi<(eZtLV;~@0?k%c0nxI+h^LaEP%Ot44r?Fjg2Pm5 z4%a)7sDeN-(tZ`~A^zaQP!vN+j*vvrGV?E3{)DX}N-PP2Sfr0x<^b@1qCYUac*qxJ zlu|{C`2mUazqS0YOvH(rNQ)B9DRi+&(;~wNMY%#t6o0B5aVmd?{^a<|yZ(Lp9|pgm zRE}-!F(<6{vr_-)Sk1(&z*f0TU=T1sw)fx=!_gJa-aBR_?pS0gcHb_Gh^rM?0Z1yK z5|0>}D)JO13Vg93@YTZcflw_}cs8c_7AqbeH$E^eUg9{hTBQI&m6F6`nwEH;s!$Zi zGOAeo&5u7gWPKdCeh|XsbiG&)$-*0&N3s}+|G+U~;#DB|lK!nH$n%JEV7paD6vPg! zxm$6#^}R&fG{ngET2Vw&FX3F1Ec2ZvthenXBt8y3)FU%8?J%~TC`iJ@NXW(sMg(i* zkT^@CHgN~&w(r?3zzalpF7Z1w0VrTgoT#-;ge7Zr|7NLA5-$C%2d4=Pc(&vDR?}+g zWTT2W@_{V3)eMOjDFHNo5G8FtYCBC`H;AihyDdkeM@^4px)PU?ZxNSE9FQzatKBl} zrtaB6=r==>s_L1|Z3Kwy>k+svkppp(BrT8y+14V6T_@3#t!E0j2CP7=8Ab`*c|+p9 zA%ciVmaIh_Qh`rg8bR0&LaXVw+K#zROHIfY6?Uu#&4{G75)Y5(*+c`|bj$PJc+{VE z&WGJFyukfv&>#DYPMnT=VHb`E^S%$Ow{bR!Ls*YzgGoR2^9w(KRq**`-U+UTDUS6k zSmmE5Y25AneAw;G^X=Le56)Z3WP;O9&z<7){L&ali|%h?xI!#~5xWHuajy$oKoIqe5J z&i!D}9i^QP@aXp^dGFHfkG%dU4on{AKtQ6MF<8MaE)$ChqnC5q@VakWq@VD+?Bl~Z=K)qX*S#NcG(Vj2n z`p;_LUl!fpEbm6|l;gkMo~&M<0E(Y>>_4EqUj;o|j_z3H-lc=Rtm1!#=;X~s;Y$SR zJyq%bI_?=+`lCe{b-M^V^1!a6;YZ=Zy}j*?zKMsrhJt{2%x(^u=Yn$7b~ zU0>+BoWXKS$rp<`ETxo&zFf=mO(rXOBhR&sId9~ul4**nF38#~S2vk9U#q$~C+TDB z`eHuMR`WUmH#gx4V*zV8J=a#7Y?JHDrIKyd&{fImO14-p)w#CWXc;MLmzB-3Q71`i zWcj72Ygx}%nxf0P-q7_-TgwY2Q}xEWu4RozPLjjsN@E4xVKKJJ7bFEvsW&oxzSi~4 zyuQgd`FxX`s+qyMQLWc?SoN)z_4;y=&+Dtj3OG}<_1ZM&dZy;cEnbrTl0^OdY+q@rHd z)TO-87MZ56*Bf2S^o^-#KpS+;RCT#pZB~jxGVbJ6gM3qDP1}G3l=XZmFJXnbR#knm zkh6`FWsUh9_$FH`gUA=lmA+Z&An<&pY|L!C?XnI6)z;dgKCkOqu4T(iUcky2L%t-zF3CFd*XFBrT?OE<#5Qvo zj78DN8eQ4U^ZIoDJ>|Bx6m9ki_l?>Dg(vWj=m4kK3Y6I5g>&1L61DC5cSmByv z0B%-mSJ7YiftkBbKK5LF z^yu3i5d`;BN8SAf5I4D(#us9Ht68@acvThVmrA&ON1Aa5&$x$czqbqfE=YHBFx(vu zTlz_X3L(Kj!}a=v9;XLRN3{((Tx6KYYCzdvBxnR6POu zNZ8inqZhKc&As1tGH(;k@0$6z*PVRsjPn@_j}Y2#TFJ{W$TKRRwlBz`cmjH8ikezxr1;7yrtgMqYM*eCA~oAbU>47qxc>T)*g)J-vAM zclIC+R0Z%>t1VvnyW|MUBH@%bsRci(#P@HUdS+Z%muacpCk#0x8w_nCsqvNXk@ za*0Eg4@?mubSM_7sw`40jX05(iUpe9FEAyp%>0H@cqDy?B&kXl`KEw0gGD@#_8n1{ zP+Tn*&zgwhGXA)DAQb7UAhSGTX+TvFVn+BSs&Y~lu@!_EN@9yhqxt=V!mlJ$;zXs0 zIC_sq-xNfIDCXxJ61WOelzGmi3J07ll_Y6jjA!V&x3j09dp@+okll#M^H&;^O%SbneiPZj!8 z8BHn-^Pke_0P*Z`?SSTGfo|{=$FNM9D$FVjM6DZnFnvjjqr_ zwZN8%E_m(ZA)?L@kLV-5%rPR1DiVvzG*<-e>`N4lPRl769;qD>Xpon-&sK{_Eigy{ z00g$cb0CuP6`~n#q2{%)foPg5qf&)FEYl@{Dl!zqsR6g|NF_n00c@Er14b|f79H+` zs-e{og}|f`T|{j0gh3Uf%E75UIQ8kETmg_QD%P&6Kq`e;zzm}ibBuhA+1p3^#TLvB z^@FM*v{z+0{(u9h(m}bzcqnEifubm*+D4366Y2o6KuP6BiQWhE6i}HMC08Tz0Q?kC z#C$?bQ7Y{hS)nAHF^3Y%)eu+N=fz4vV)?6%=puQ)&_a~T@A1`2;ZT;Etrl=X)v8Do zorsY+gsSqfRw*GtK(@lueDDdt3;T6spCMKhrRt%0Tyh#pOKCWCt;p9tNi;`+!SB^j z4TQ|4^dFatBvf7yP+=d$QQ@TmkjzAdBTkV1OhfSN#-I65p>K53w)J$9>mv`>@(eGYl(4mK?jvC?%3(FImMVNJTgfie&h zY1Tp@EP;bNLi@i!ABr?^cOXy|MXDcgta@tEsLsfL0{o*wo8>qHfp1Qs7f*{+rM!=* zQ}V`_63kj2wP{{K=pzy;aNGG<9ao9q!S-n62vWiv0Y)UlOaNUVRPs*PgHPPCDAUbK z*A*%*M*xICd%v7arKki<3wv}Tv;|5`YNs?}LmF-!T%D3xWB_^!aiA1RJpDT? z!w5j8GDek4bObb^ydaFj&<`!sZwI~~*rD$PVHmoW-fBCx zZ#6yBG(6w71J^JN_!=6f83lpuMM2_|vJ}hrLd%N%$n(R9yy3(PoX~Tvw&S~DV8dtR zhprP^z5}2Q)A6F1kk$?ZKPHhuLV)8~dO&I<$c|aA*)}5&fcTN`8CK{9w%&|@05^2w z(6M~WiTuDM@1qEu$c%wM*Y)ir^nlpymR%-L5ypleC$XBhI1CUt+G@4#uv|K+7Og93=zSH&{vP&1N$`U(- zzHSo6iRmVhWjjGLj*?aslC7}9ATn(~u$+Kw!{s?q7{*ROwjXod0EqX=OHD#24%;#C z76c@p!fp8;c>xKq=aW2*Fbs^F{mDRTQSAFxOi+eC*-9(6po8c5wguviU`${)otEb~ zkpW$!BqBp>Qi9@!zDf4va*WV)LBh7}IzbS4y6d$K%K)UH1KZSFE-1#;!_W)>h7-GO z(+3tJp9tBC?7*=N+YDR~Fc?M4XgikU*}iK#j_bHB0@ya%P2F+ZPTOuZbwh9Krr9!^ zZN2GPX4|$c%l3e-5LBi+Ez{La2ed`h=@Sm3Al4mHiWJ151zHJw=zGLSVYh=oOa6w7%k6ghfTc+I`)A; z&)1F6xKX1Yc(wty075kbGiZZ8!Ke)&qX{DNNYYQ}>7flo5wg6jvWADRz*$SBiUPENlw%vuinuu!)WO+J;6d+U@abb{So|U*t*_o!ce0H1_eh=-O@d` z1vb?Js(@^_1zy;(uCO*S|Emyyjln(1$R%UMecTR3xoL`!<3H$ z&xqOp!UaXc9WH^}Qrsf%fmwI}fC&MI8 zy2)q~bX>2Oj4dBu^}54!+y{wFtib5>LGi90jRw7VFiLtp#>N%gn`dsXivurM_@m&; zN#TaQ410kyv@SZ>jr({q#ID)zIXG!H+as7ot`#>i?oP)p zP@cxP8+c?pHhh82tR3T?JGNRlY7AgfVb8#w0o+4UuaBc)FmkZb$NhdUYxg2|V&RFa z53yml{Rj`IQzOBox(eipN$FmYbRBIE*3?$diCjs_m!`N&0I_++fOyV(~x!vKUgQHO&Cl}*>XJBRoC)Ac=T+;;&pj^emG2!`zdM^?-1VCWqV!gPQqUSQ&Qk_Mrl;!cW_t6tc_Fjc0} zAibDi3t*cO?&8q|V?4+GaqLd|QG!7R*EqsGKWO7V#x5y11I_0cenuA9H%GnBU|~;& ztr(O20JAhs2BT5lnP#2V9NU$Syn-rO0xPykoRwKB%V$a7-Z|qp`dmZA|s0B1l zamRLHVh!h4VLzN+6En|XL>lz5F?Oc_r0u4DWIN4^76t*sL}=mI9maMmNP)g&(6Rj% zcDx~s#Eu?z`k@1;04J$#>m|TZ5|b3d9`3uHw3GK8e-h}}PQ5N}GA0V|W5H+z}W{y92+H z^SEne-Eiau*a&AZ(J&r|`haX}>4FBjU6?H2G}3;I`!*iN*v7bt<8C+^coCi?1B;{} z!a4Z3B>Mz*Bb<1d+3JSP*4PV1p-(oa?1H*6Jko&_FdjrECS;BV9o%a*yh#c_tmK7W zVfQ;ca^~=;M-n1&(@lxFbl@gsz*l|H8D2Tqn!v=y*46o?huaq1eR?^@(;hqs;RJV0 zr)vTrn8R=f@G%$#Hcj1a_XGSb+;#M3!ywxywk;Fn4)=wb?spn-=r$bOOkB8MwQx%h zgBYjSY+LO-N(b<;2SoQhcr zpqDn`b_GwPz<28+!k|wb58LDy+YQ`S_o7d9&^LQ<-R-(zJnG^rn0syC1hIO9sAV_X zlc4YD@O9u#2AL7+*f4M#l-?a!?c^?v^Uu3K{`QxD7~G|C{?~uk%l`X+@*hqA`Tsf1 zuKx3@n>5bwS(@RqYC-rqjBn0`k24s%_or?OBEz2ZByW=>D0arE8IMEblW^9~UqVwmG)(_(>Tb8P&fRa&SXM&mzdv@#76M2ltZQ($nqSB61!l z?xuH$ZU;Uof3$9;@m2-njl>_)T%#V0>A#Ul{C@856Fchmhy)&|_CDY;ANThOm0RhB z_cGX-n7jL`OJw}Q0tZiK*$uA`48VwF@ZN^0uf0O8d!Mk}d$!4`bwkFpq~NUy3?C_D ztJPas4ad=a_giSsvZ3!NPjA6IwEKZO^0}XnzqRZKsoX(wZ;wXs?-9r8j+*Aq-5l#Z zMfn(AC)jC0x3@9#83*zG#al2>u8x4X=Xu}bTN*s)apfyCE4H7Nj^Dycwiup^h$zK+ zG(Nt+f5h=U>wv)6!OUHIxV=5t!6OEYn;y?@f+Rn@cUPo)_QU+*e+^#dhky6w`Qb?# z_kSJ1GxGp#^v!0~Sa0U5m7<#ZJkvI+yvXbMV!71k%av}fR`umt$v5kTtY%t$F4yzC zuIk!GS>M&>_1I6(O4<-Oom>%EH41GT3;_TZK?hAnk;KduFgR*a;DaE@?y5d zMqO(eNk^B>Y;DffwW4pbm994G`l7K|=kvuzpKo+?K3@U6jO721bvV7AZ}RngwI)2)6|*j9+Pp67z?HsQ%-0QVr7OAIP|Xc_-Q0Y=QkU8a z$O0v(K$5x96$QkpH|BtStuM4J*XJwM%obV>S3nKgLSBO|=44k}eYsrLH;Sn$YoJD5 zZnU~a(%|QH6O=ax@nu=Q&eaA872vEJ^M*OEuNAGKD%xVPB2^2zl9_ z)P8C|wV&GmkJ?x4p8RfeZW9)F=QF;@d%aDKw7zOX% z`pNg;X4hzY_x2jM?f#;3kN?Z`_dJ>TNkPJ{T2WYuRHEU-YumUBmCczM7(+J%)XK zo7j4v*8L(4_Hhn*_Jq2-{d^ua8lSz`#XQU2Osl<1{ol1~_gig8-u2TQ;F}H9pUU9* zi0t9Q-K8(fmVZv|lYH^dJFYzi``YH;k08B4$MwB=e_4BfAE;-=9*>3g_|mgI(O-aj z*Y>}N=C6N+E$AAAe*NOj0F&g-%x&|51H_kw z7RQn_-U82}3NIp|bjTqFaTNt2xk@obBv4G55%_K5aEUo!s3TbsD=f8FWf+O2X(Z7c z^8tx_Jca7Cc)-@_VvFWzy2el(&xz6pp5Y~QSl}uo^_N2;$J^pQjf65q^8$5vBqFvX z6qpLbpfbx)4LvlfHR15+uml74c!>pyDm){IqCitZRbUajhnR8&9n=_B0D4(bK|D_h zw2BxKe-&sM9o1NY;~BapatKA*iB+O&?18w?(M6{C0r3TjJwxSB2o+UeJP;|0qxWd8 zMoKRmAFPfDR0RNQuQ#gB6OXz)&sWBdS`6 zM+(|6aa@8J6NuqaNkDXs6t1}sGm!D8dg-+A zfmRqw5LiW2DTbj)_HM1x8ZyTfy1*c@38XPKo~xk(jhJc$eGv927Kj#^cCo?(%ZG`= zGkvxq=?o{;=mI(}X$7XiAf3|C?zdYh;T4E5YiZa(KNwio*2NhX5DJbX?5PC>r zDgF~xqPHp6=&(v1&L}Vzi-EpKvcuETiKOloQ0W-$9~KxwC9_ZKHGz})(-KcADE4`l zIa36ZicDpw##4Lr1*7lSc|oOwOOS-d(+GiJn0?9M8w#y(0$NGm4~+4HRxC4>lFStU8L^S9E@uIK?gn_B565@}+a;lY*1XjwcG))&v%%ESu}Fl| zGCJUBnFB(&Q(mHYR2b1pO=b3leff~lOiHE{p*ZUm*_Ko?r~`rF3jm5_=c_RMpait{ zky=rTp9Iz;_yk6fD(yn4ED`W{@K6@ys5nm8i4?fukI_sniWJi&1lrWY!}(LB%5$ z^vW|I_6{hGK@20CTva?PiY2y8aUyw(HBc>q+G)7mp$c0(;yA>0X$DD$1yL+i|KLPW zO$rqmn&EhHcCaV!2@JVe@-%rDxWtlsCrDa2ETXcwx4n-_T)D~!9gzZS{kh5(iqsKB z!>x;F=>kWCaZ?{lg{mU3O(X!J6@fk?H2?*!3Yssl4B{&msm!6uXXuzZsv)F*l36fs zRE`l#mDvLjbOAAE3@V-0&_{(U!2D)7k!=*qq((yknov;$*?{gCFg0Qc&2fP%epKN0 zRssD>T>Aq6mZ}K{_r)W%tPlZE)F&5_9TDMXgUWS89qE*+5aIwTTYwW?MCLnuJ*ZR! z&{9dD4+W0lPAI;FBB6x#e)HoGI!O%GTY8||p%pr=yhKyX5f+6FGPOmdk(+~j8@!?;ACI~q19@_rPwsct14Pyv*kM;d82aR*?Qo&94By{ z*mR>dP(WVS-~o_;wDnAf z;{jEaNLXpPoFTqiI9}j0_(KIDoH(Hrkt7Ih$BYJ0m}3(qE$sauDM(b*Fv&O93%y|e3Ns}0c8=-^MMiRmk?{@pAo4Tp}-qv zMNp*GBp{mr1g>NNBom4K%Ox6?15?Ut0d}nb_Co3k7YjWq>VWMiKO|haN)TW9M46xv z1TS+Da3s>hAJ^oLML>`Wq)8F;Zkxgixe7&qeYZi2)Mf(Kqh5)?t{}3k%&0srz#8Bj z&-G2>2O+~I-<*;6?#9Yr!lJAJ`5Qr9S5@1e$?iX$#^|P^! zu#TJ~s2^griYR(3V>SWXCfG?H8>qmk;BhLH5yTP@7kCUN5>XfI6Wg+Y6v4NJ9Z)zf z3^19(#tNtud%OTMVPKUY`>{&&rOqi>Po^z>Zd-Y(GaY53$dslE%+m&{3~xswETETU+VXrc3IGL|yYh?ySi37hK4IAW71k(U8xI?dBiYl#is zwGPIg3O(VPJ3^%a_8X`8F^hDPO|{lh`twW|ahk~mLUv7^7R&4d-0<{;8-_Zf>Z8t5 z9VTO;Rip(;XG>}7%K(ATCQINbe}iDnbu55rtbnSP()ys34wOz+p4eKlmDW!3LFrlU zC6|bpjwjmmvcl8Sq`pq`&sr~H>FJcYONsQy2ry13dZK?RE@yHy(JWm7!}^yCY*GS8 z0vo>+ww}bF7|~(@G^dgKi{&Qqh)bQuR%(wI3pTU!DAJxZ&p{%LDU{4PpTbUw#J(aK zaKp3>q8XhlVtINN$#WLyk9y*2mM30Xm^!BJJT|HONr2E;PPBq`as)K^qW}w{g2)^u zVgm2r0b+V~4C>)I>H=}nb{GNIAt`h|%Uw-akft$wo=1#~iy3fwt`qGg>_U4Vau!WB z2>eoeq12y*mk~XiM1`=^C=!_nW+3!rB7iI%Bp?fm&@}Uzj$*-zjCq+39pAG=Sb!nX znT~@roXQvz4{|ytUaa*T>^GBg9NCx*G6_Huq3h|D$^;mumxGj4O7xUYb1glrFB>PR zzL@F6WtIlh$k9aS=Q4-;AG3*)8VnKCB3z4kiIxcqXJMQL<7he>kC~<`e+*0sO%pgv z!ZCIhJ3wD(BhWb#N@pt8Dg0ZRqV6xHj(nm=bbb*Opad_)rZ=_~+vY^+T;?MEzyqJe ziF6`RfTbNzI}3;)wA8GI@CX`&IAhHv*f#eq9fTJ)0;KVQFIpl7Kfz=K znw{y9$1Rz;G0QZ3i{aTNJkWK*bEW4g6XThiSvvOez|Z9>a3|h*4631uxPb#Q(n)yf zIH?R_cAf>HF2;z(r#cW|V?NC&1+9Q}dlT+Y!B%;qEeL*os%4a3h{y>hQqOF#F$L1} zAr31thVPL10v>5B5Rr=Kdg_Zfc`7j@;DoBYS~qX)BPAH=a7^3u&xk%ZcFGGSkA+eC+CRO2Y!4@TQVE zMz}J;MTi&_KhC}A55PvECq+7m&oN`1FD#uk7E{-@mxxMktINTirt{1 z03v9nr!b9w)YDsh{(lvJ{rA8B&*Y2v{6|>hBFqrO%=Q7MibAo%$O(_lVjjT5TcP#e<#i5V+R#OJlMn zS>7GDBP4dab5cT!C$}s-9PyU2M+3gFmK?_ADfE`&J^1++GLJIK@2+eIzq_}O9o~nC zKR!6$QO9=ELhjz(j4|$u2kc;t@8Q4CVC0``=3^rw`ZmQP*t;c*yGqt~s|y0}H%SmE znBXpDV?%(vH-iF|?`#O)u)3EDkd(%;2ewWhNaX(GmcHy!GDt~R?(FhE-7ic2WC{rX zVqc|_mhu4gKqBSHw+G+pqx4?o-_ba^6Ib-a@+UiWxm$SsZEA-7Fr6TNfb$P_?x*{i zA4w_noyJ!P?|&$S4e@;Em<+9{xRs>Xl8FpB4^tcVK5tmuSe=U>?e2L1awl$;8ul>#L{b8@bd~z?`_z|>U$;Z(CfBbf6e-e$;|D`gi#>Q$f zyjm}Z%l?gZ)n5q&2qCnxA=P1^DG^aOJHBWfk}{Z+W)t57vuKP4V8%pg&)oUEi#S%hBNK z>J0M&y!C26fOEVvES|nv&WG!p)zx~?TMP!h{?$#tkIlgPh@Z!r@blHOXU%Wsy+QBh zdbC{jt}JVG25<1&0^6tWbNs^RnX*{IjMw)zPCE=$A@ zytTDj-@r#i*7wgAi*+B1g0Dt!+Un+JFuYk0hRd79^?Gr=>@C)3i#f^%%i%AFmUVRn z^Oy7fd@=N_)qJ>I-CTLS)z#Iazrsw1-l~U1@Rw)n^?b3!#DkmuVBTBa++3|!))3^@ zUyS-d=b{HpFVE(~t6pz4xS3xqN5H`i96P_hzP`aS@AGAEFdPoO>;BnlKEE2=4B<|{ zH-vMR{q?HXAFh|{tEF{wJs5yIR+}|9!@hN6S?jV$ytlX--t_t)ujTyeW`zk9*y0TI zHyo`%1-)x;vBGXCf5P^XWs-`01(hnrGFpzfEY z|1vdqh}_LICwvM->-oFr>8JZ>?$t`aorBnRhm>#pN3(Y+cWFt$V_LU`w|zuT?_Rn; zi*CvGo-B%g|M?48-p%AM2+F=E-`S%-d`$dn(Ud?kvczRmubI#N_|0;Dmi{}pz2{)p5}kcjggcX-Z=8EO z`)gE^Z&QMQd*FVO3VZ1CUmD+>!F133ZlO zcYl5c%>AJB`!iVHc?psJb#KjHW%BLc{W|G;%co}TuFjEAos@Reh}n&R{8lRK38Bijn>drhdnl78^p(fZG=c%s_=o>%Wx zvESS8%OrkFnfQk}D$h;ZzJA^lCs6R=3A&yc_i^kiV?U?iH;rF+7%FLWcaWusQDxz%Rns9rY? znvM4_2i4=+pbA&I2Z$NA-ZT%pHUGt_QGapJ=pr)puvQ%z@89>Tt!}kmKRB$lD@M<% zG+$QnmhrJ}RIA6024bL3s?}EO4OV|XHd+JLA5Pnw6diea1_)Zx%N z{3%}75Ov<{Hvam3y;L-oL zaoqrl>aRxC`uoE{wR2#=l}^JrtyhLMdU{^{ht7xYn_;C6vkv=BY<~_n?Me%?8r~io z|MQ^U8@B$(A5Z_So*>>9)Y1Oob?sHJ*)tA|Mz2~ut-d&Y-F*Fh&1iM19i!8$0fDud z(f___3=XQ@rcvo8gU;FDhwAB%&Dy6%?binR?&x6HJA2WsR;ra3{c5eiG27h>l)$ z+g{bEHEWhp?Y=XBp?^B_`bS5N6XUR5wlP2qvT;y}Uv-a8oApEE$Y^v1uU=KF6%bnE z$EMM4uvQm~j#rI0hSBX9#!<5!z@ig)+wLEA!dj(jboxMqaaI`|i&ypV;OGRk(Qm#r ztJPO^P{N@Ryso@9Pb(lrFc9O^Fsi)LZ#Vt~8`UcYcPjjQ^*8_W&!6+5(X4!jhH?n= zdTrxX__ASi4qhf;dLYr0m(2lI!mk>QYPWWXFz1i`qZge@!LJuy1%qvHx5*Q!KlZ>6DxFuyhi2;y*nVqJA@$y$kKO7Uqw)?^Juo|EMgF(OaaDpBR=T|2 zFy1%coK!(`hsJ3I`w?JfjM1)~^cvt9MyGq!JUIgQJpF#~rfN5g`kPMW_*0|N8NNoS z_`z`v{IT}kkF9F8)}0@=oAZj%|KZ0&kVM6BTCG91KKNs!_p<%6Q+wMo2FZ`LcBj>T zS*&=r|=MYr3n@eWTfX-8eWrZ8otb#DIguyc#%g!*~f|Hae$3Y7dR$ zm)79>V{8I&(&!kiM!RO!OibaZH71>d9~uXC!+m$~_VldP!kY25!=r)GsDT%N-#5^N z3ZskiYV;fRmT_F^z8lovwBXZ8qt)s`kZkojpyFDi5rgGilx7b~_>cGh`l9`ZR=2Tg zLiDQk@$5>a`>Ol)RmW%#4uPHzFxRiPz{q>X>o$Z-&_l>izbgULLgG zHmYylA6AT@Vf0%=*t~umx7yuq{q3OXz3HD~5(+ro8wk#aU_i#8RXzT}IIX=XJ3AcK zEpFZr7@v>Wfx((yIP=3{m|J#G(U(HYGTgNI4ZCFxpCC^;T^bL{qM%=C6M?u2|5t<|STy83(6O&`{b9iAvV6(u3TP1?qQCONjL~Lqk zDn+9}!di+|oSjxEeE z1Ok*rSs+47Vfuq|g~OQOl(^hS$hpFH0F)ETvHrIwZ3J<9wre>)mzK|c?%33H9c~MY z!_-Jh+(=MiDc`4rD})jUBxHg(0p-Hwu4TeI6;S3%O98oxFy?V9U>@w;vcLw?mE(CppUG|8#**KGbcN+h&NwK+4g@R`3Uf3h z5Rat_K-frSNU(cApcK~FXAFo6gadMoY>>Gks+6|?u7$0zEPN2Ez~Pt+09plVuv9+} zm^8U*Q4s_T>+>_}D8#-K#(hZ`uwa^&Z~G3GCAWY@P7w?(NZ<#kH;>r1M@`2iJ`;$l zM8{s8W>09I&du5 zA#(|sE~l<(6W_rEBdh{15S$-MN+4YLf=F<18NsnMB4uX*!KDBu12C7s5-uhKa4-sl zvonTy3rv7tA%dM^Iu17lIIAg`Wl839>N}L9%* zkicUSD5RDHCJQ`a(SPh%fJ`ZjORQ9*jY%XDwi9K-5T;NF4`PF|8RvvBg=q`$3ZW8A zmnsf7T>`!@(c%Mm6NDga?4!Ue#$m36;Nw`Xi&L`xQV;Mb8P5nP17;G?!_qfA0f>jG`MK4B5X7AP)pA;e;+29d&%5O85+Kz3RmIYypy5MABtFCQ1 zToOzU(2h=)B+!Y@Vyt$(Nc2UhwTO#gtS`gpLi#hM<#{~Og6krmO|*)+4vG+~g2&-3 zh)EJNok}s)Zjwy&Cs72c9!sr1=3%PN=izzE{KBINJZq%Nb>0`)M29IMCG$j+MWt{%w)?)J$KdA#xO1ZjvG5v}7Ak|iCq(H>Z3nOb0%Q^7z(_HJm7hP6(4{(JBb{1WuO_&+ zqiLbFZAA$O(SWc$3$B@3vpAjF=cz3(DNN>8GL5uymVWec#>b?r6#jEK!z2j>p*5Xi zt@aCTa_!{~%wG_TgA`UjgUI!C`H81iI6@7W(n~Z~*=IV@noc5LlPDYIoN6mrz?0hs zHpfiZbUgBupV-<732{Y4J;#ZGUJeW-wg?d=e4$2Q5MdJOIEQD3GE+ZuB59v_Qm2H5 zvHs|dGsn#$ClldZXsI*pYnFz5sXdDV-EqQ0dxF_2k+Ag)YlVjl!WlDlmXCEXv62{D zF(fmPy2ZgIK*YfQC5ZQON(k7>L{B8hItg+eMcQ%gbP7)vJ#mUrrgNDrK-1A=8e^A) zhva7y+iXT&M)i z=%cpJQ4!-5%)pESJtk41cnDvOmXSTd6qGESdLrg;zB-tZ^vD99 zUNDiFxG!BW6-i{X$EGj zKf9VUu*f7)8Xkx?@{wsf$}>IA(oC`Oc`h}0G}x-N;qgteze}2Nv|aZcOkRM!Pr-OF zg+>u=CWV*;g{D&lAyun|6lp-BM5UoG_0$Pth)y5!nA@kWR)7ab~0cC*)3NyMa@`d)Csro6@ZVETenHxalnGu2Z0M^DYofI@Q zy$B1?5|1(W2pvAr5YWN(EKmEs79l)QRAIwo2qN}O$CvWMrJ7A(144cZS1OF>S(xQ< zG9|7~J)KP;I`MPOiy~a=>B`rIE+*JNLXWZM18kq90h`fal=<4dfOshK$%XRt1irQ_ zuorDXK)MiGiFlG->TR+HRr)6@2+Hmjm-=V1(s^8XlQhO`m|VlRmy0kbq_|*{z)m%d zE;8&06(*A+Ps&`6pE5lG>Da&zyG~8{bHiP7V!CC?BV+Ffb+L#)yWR_y9B8sT(kt&?qkU5-M$;l z>i7;+EpJh(=^fH^ADKG7CkknKSTXzI=gs0B5G&$ov$UiSPq+tpCp#yFY=?)3Igm~i41#SgBc@iI94v7@pt18)&x*_rjS1SD|+FC0Q?!}I> z@~3%t&)`OScdSMC7vt?tx16bay!-9DVn1^OQTw+$75Bz+yY0pqN_ICEu{FYCS9X3j z*&LodNVUK%Cp$du(z`RfDP`rko7er^lFj<K*MkCDKCHDN8Z~*AMPC75$A3< zcs#bdl(zM-7ecx7-gDqlo&Q}P_mV621}=G&H1OYz$Y#S2<^TX6iwFb&00000{{{d; zLjnNiI_L3pJJQ0m@6;Gd%^CjZ~J~<#Hl** zyZyf*C5F}(bik7c3W@GSBtw2Cc_lX*?LClyxF{K-Yw=WU0toatyU{vEzrGvx9+s( zdS`am?%XwL2WqtQyag$(?!2>Ht(Lf;wr4Z7vu>%aR;SsTwN#bPJ9OEmxRlR3>S~tH z*2}w(F^uGdg=(V6S5 z&TKwk+^xIox=nf-fm-HKD%4D=P+sB$y@DCv$@XK zckB6Gd)3Vs`K&cl7p-LrA%Xi>%T62dXmgi$VM}YKcRKUgY`tFO^VULDTg#<7%U7M1 zy3(N|G=NDt^wsZHD|n}a0C(n{W*cfQo4CK2>2TRhnlINX?zOpYO}c97 zb2?uxSFN_XoWmy+0HZqGzErz(*;&t5t956l-Yu5RS-aC(brFUoonc~qjxVcux3$(g zm>ttE;8p0gT6CJL*&O|8t2Kk`R`d02-O4*~*$NU79(Wh%>R_%mW@@XQWviXvA(VG8 zR$Wj)t+k%FV98Qlwjmy^rFJ^{T+N|)Yt^0u2@Bw8#rwi&b-qB*@0#`qmYJP16Lhc{>Q_8Kmk>$%#ZGrB_ZH1+NbB9RT9E&{l0QJzHW)x5o$ zsYs?y8)!m$uV?M`3L3ZI^A_}&wUMd0iqPje<(Q()R_hK{z{~m?39@Rh)~(Ln9Fc0x zR-IW65Me$r$!wO-*Xx-Mf2nt^&RTD;k*-~E!Ft{9P-OgK4(KjGEFc?9qpp@ve7#-* zM@W=K69hC{Hdhp0>~Ks%ma0PU_8Oj9->m>Yo$`EL&0DnH#jLY#3uddWHErJkzU?*e z*m>a6kw@X^UvNd6T^ zv)K|_tiWDC`T~A|+dB(jw|NIpau6=@ zech%r9e7#-GU~EJk<);K4teXl9M&PI$i`(GbPE?PmIz4Rx>Gwj;CBb~=-^nOyn_UW zeywFY2dknpPfuWGhQN0rxQQIo5v=8W0g&;K-QDG@J6%QQ&K8u%^A4bfu8R)%23Tp& zn_Un?zM64j?B+Af*~A*aa&r>%8$%uIY42a5hy8Xfo``Y3aqqc8&*iw=Yu14pZ&b#= z|75;xK=LrVLzA79RMp$B1~rb>_29FN{0rPVYw@bao#u z+$-#CyLsEGENbnpx*Ozq_T%2kw&zo^-hQT+72isy4;Sf^PQHDAnZ6RBy-54X_y1?@ z4OsYYX!mnGw%;{hxcIEu2QuD@A@AF_pZYf0Xy|ZFj2E5uXuw7Z<7pTD`&!)_YH|H+ z>wen%8}>$#H*?f?%>1SvoEYfV78`$F_pG%y|Gvv>xPn3Et|R|V5npN@+4b`vW(0}d5uDJ(Y-jo;iVaM<9 zA>PQQ_JMqFhn7b+J<;v)tlmrZ2b(c3Zz__*74{n%J!vmE$ay-8`9wdinZH->g=kRg zE$qy-;oNzU<=@TMSK|4$ec$(C_Zrif`>}84o?kWVY%1j@mybTAKm=+ z*l+mnb$M^UeY;E0+ZS#5`s~XyO@57=HnIHrkQ%oKJ@Q|X<^PER-iYJQ|GKy3<{RqY z?CIcnVmwo43*a5u+#w{IVQy)5V(Ns{OJFW>jyx83$M*0&Ez=D$3T z^VZU5v%GNSHMKBn{`HaId(Pf-&M)^wdizWM&;!42zhTYS=eHh3@(u9$)*ARqyLqMC z+rav2ukQ{2`h>9GB`Z=dDA}e?8FVU`6~MBR|`P+-`?_cR&2%4*Sr$+qdxSH)K3l_{~m!%VfX&LjLaG z&u;kp#xPV&IqSz{(ofZd;Q+~ZuC=x{^N=GQjrH)_~q1Z23rBs&A zF9b=b{s6(~Ar;YCB*jrlDgRha+QJd6D}J=G&JFh5;Qmn{QIT2cQxkQL0D{}FS z2$D?BY9Ey@2}!9as0K_u^s7uWRyIfVkVDyD2RqsKgYz)nX)<1^BSc z-$5^ZDsG(BCavNJ(jW!lR4Eke$C4_J3+&zY< zHj$d-R4G-_nUYddC`d$vrBYKU$sg(hM8I#=qmKeSjF=0gR1_2uQIU^-ESAp;P)Na@ zqJ1s$i%Ll$$3$$4eR5H$pLR=U(+j0Otd+$Y7f_VQb?Jjl8XdUKC~)^mM`btw z4m*Y@SrD3nctMIKQYkcR1s;zIDHM@`1!!NbC_;n$K%}Zr5}TxaDiw?EhS-th@)0=_ zPs^3MBA=<{qI{+(vM84%MOBZLOT`w;L^vvm8X-v9cBvPGtk;U7P#2C=0l=wO zYVE2d6izfC{(YU)MIO(3Q?3h0&w_9)1LBAX2b_8=s{%k&EnE;!E=rXy0%d$SS0(P_ z1}Uq8R3~xs0v1Rrq9RmVGWpczQ_3Wgh*lAh##Kcj;*nC4ekdOo3I#Y;eOD;vzdEW*5ht0V4AXup08E~8UY0S#F(xkjt1^t8Lv(Ik zxMpM9w)4fd?fkKA+c@Eg?GxL!ZQHi(RH_=)xt%+9f9=j5dyN5+h(hs+?S^;CY~b6a$`^ zxe{dltfmy==sZ9-Iw*z>`2>ta7J|`P!z%&Cgs*}h z@a_94i@=;XX|f`bgby*wXsA)j)XE!8q%15^mGiECY65Hr*-yFR@ON|cm?z}g+HV=MjVaIO$?gB+5Y1z z9?=cWy;Os?#;FrD)V?CkVn%JP)~j)uCMS(F?w4Kf+7 z8m_W>t4N$?fYrl)B5^c_5`Wfki2B~kR8TI;Ju8u<025ykqLYqg3BUz)`*E+jWlD+d zalT%%FzA5__wqD7sbpn&V{8WPt}1SaJwH0MD<%d?oblR54fJYgZF7x_Rt?KUAiea> zZ7@bm3eMA@gX3TVE17x$Z%9SYD3~(G+p-Ww4e9!inLIs zfp}lDfPci|IeuWPqVx#`8bovkk|{vYe`gr*d@TZ8LI|j|xJN(=X~=7ZzAAG$pM+7> z*bg({)>Hg#s00?1wW<^!a^>qhg1Zzy^5v2i6!N(_zpXuVki{w`M|}E{GKR|gTTn=9 zJ(a=$q9|oEn7)Sq%Yd9Xe{?0*a|C?@p?n`X{x+n;{K|05l4$xj(%13hs3+sH)!j~A zDykFVFZ^Pm)1iFnn0RY&F`My1ca_}_jJ;ExlwfBnP}tb;`)*Gf-_n4?5cU!%p`;-k ziI`wHt)nakx6FUxWGbR*zD}RO&RCMTHc-9uBj%#~JT=!;U=tk66Cet3wJ|V@G?au| zPUygat~W&yDr)j*z?IsVFheq@4l1P4v0g69^JjIxcss5_-hM5O%FkVoIQys$wun%r zD7LktstS8POpd(xzyW-)=W_t|p);ps-8Lo(Af_b~SqhYA37XNx2fx^D@ z#S3|`oU+d)zir@WkXODW-KCnf3@e%&TrDKa~OG;Z+X57;43(;upC%{oHv!_0p^rTKFe{2r=ws1H_l^up(7p zZ6cOTLN*!tEY(P#IokGOjaJ2W-0uIY2cJ)`W>x9X@_=N^aH@Njs^ckN<>u$2wK|mi z(T!KJGT-m;sv}Yg7NSR2I3H5$(okuaNTKmqqB(_vMW^cILfAn)I$2m(z{EVVxgTQxKJlE=Qpuk|_VrrAMH7TerD{Ar`0CA&=kwM>e5Y=*@^B8n_b5 zs?Ypto$btDHd?qTphPeXHWyL^AC?$Csz7YwA({Q(ct%cH;dAb0bTLP~b$$vMkqI`R zRN<7^J$Wo83oHpc8_4X7ju_(+>CjLA8<|J>RBE66s^ z42Qmqa1BPKz)3O3!D-_AK8C22Jb*%$3JAcG5B3Tz=AnS!nuU^`V#3oIB=TtzR)6@M zWuX!uC@HQEBY3O_z?49GVf{Dq0{7nvV8um*uGu9rZ0FeraXKo`4+L@zBL9Z7+w5Fz zcXjhGa-#z8mWyur8V(=^ZX`rNPISGb`$#koKa@YD20w@7Sm@A*hz)D9t1urG{PaA;4=WQ{0aS3MJ_{&N zL>$b4Ca%)+ww*9kez2~Bs~MT+w$&~qCh>Ka1gz30=27DWJF+jZx(G-CrHC2{Q=D3% zhfEUG0BU?tD`}mPI|gqT85*e_qdo(|(PFk&bogVmF}RzcShYo{eC(_gi zeQbs(i$fVtI9%;`F%3W3 zt3O6P7g$^dc^UU)1VJ02+=(yahon%r&W$jp>GXEr#lg_4G#c4Y=U3i`RCW zR)N}xlw@Ub!5pj(-v#4sGkYuk7B1%ft7;q7BqLj0Wa7KcMo1G6By?(jc7Y5Kantz4 z3Q-`x@h6@Ds8o$?TgPW`@sjwW^L0M2vySnq*+p*{z0=NPf?BQ32f)*dAf3ds4scVq zwy4TjkNpQDCmcarmyyLG}-91N0(;9LVoMLF#P_Vp(t)uIoFYTHM{#75j|1st6a)jzP6JL~pMD{zUgmYrs(RmSSsw z-)TZd0`F;%@v-dZf{~ZBL;BV!_k!@;@0A5x5x9z=!a|$LaE1`i2u}ppaG^W=*y5dW z%11PDxKM#WK&GcH*4conz>bW>pps*uZ4e*nfdux+Xl(cD!j7>Je&63~CDi%O$MD&ecXjn1@ovHyA-^!za*p46v9*M8a|4sjGn^2>^QhGc^9p z3JC>+*PRelkHo}sOA7y*NAEPb*cX}&P2*k$y3fcbQLrm`$z^k?TMK2xkIF-;SbT8) znSw|)&^h=3SIf~l>gbY433fa(e`H;YBMYg;s)MVRhIUwJ%?$pT?Ycx8Nfq#y5ZValD<1d+zKUhB^8#*g)r|{`MgkIzA)qG* zw+9|x)qri_ST{7JLH^wc8Im7681tinVZ9~YzySc}mT^XjL+&zvuSs8~28AYh9qb~a z?fZA`L)(dW5P|Ik8BP(k6%<*If&aeqzos7$%Ah|(2UwjNnKr!*kKDecpyC2&-t-Bc zwuakcPDaUgKSM%Agj|8;2H6amO*`|7LgOlDH-y?7xB?qyYGBpM1x~GEa=k`^FT>LX zop2?AFAVzp2c|q|hUy(3a6XzCa9@PX6!7v&fql_(e4-5B zfh3662-`1?li2e!kz;7Z0Oe0eVl5$i)9_6cy9Io~R6raK~x%-6&wVFvEpgmuYcXYcYuRFNWT`Ab!KyOD#t)#+N;ua*Z`& z!2xV)B~i4V!Jl=u}g27-kd|fnuPsq%g0T_-hENpJiWJT$O3gJ4Vm0;#_hTv@_m zrNG$5G_PqA!&W@fMFblK&4!xt=v8*+w=DaT5YnRnnL0;?Bdf6=tcmof`8))Vjo~q2 zSfG?3drD-?%GNazi20QE-7#opmQ)|^NpV4^!JWkzS|XTQtS?TD8)SaAe0qyZ|8zJs+WPmh; z(hVJp3%ubwh9Ak*^RVD7M3yOt8=AA=p8RqM2d5|4xML$4@L@kUM>1nP9GYR|dUSL} z+hXR0y#MnAs0($u5N1{S7+ISbaT$Fr%WnK3XdLMCIRh6!X8 zlKuh(R;lU(xHZ-+(zbrX8I#Dx&R?rhpag^@mG3k&uNW8T|md-n=*uzTlrp1RefC zBRD;*tYRz&H02iAfT*tbAaez5QGBsf0= zFZy|c+dcyk#sF)h<(JLCf47shSY$*!d?^J5*I%r_-su7j7r^}-M}z&xE$tXVNuOLF zlMU1`8s~q)x>k*H8fHY~6%A)`aiZjj&@>|(6l#9yXostF zV{NuR;E1-D-Z$EX)2rj6@PMX&0kLRTDx0qU-usAD|>4j{{#?k|K&u|)4x3n z##>6jqtE4X!(en5!9!(E78yj2(8g*<@W_D4%U6+B0Q`rP z7krt3u3sIpO>y*}nN~#mHVsi^{L6s>V(@+Ch$ZM>TVwB=pMa#Y;C4@A38@WFS_u4J z+!USvctYRFYUq3Wn4LGDL`yB?U}9rrIN5&&lsKk-8N_$B@(duit!`sKE278#W@d4E zZ8m68Yd$!dfS5qGNN_L40e%eJW{+QK_lKiV>mS`U5i>u>kJSRKO#C@l(Yo+9LGnxl z|7J*)1~`m%V_uMADc;7{hbC(i3U+3q7tUw^e;e9Tortz@+`W;j!0mKGa~J2;Xt$R_z^mFDpUo zB=qg3qv@j&PFeLz@hmsjWIbvh9$nLX^^gf6c3!8>9s3if7n|%=_JJ8 zeL)O7g5gYW@4a`(Tp!Op+W6@eCGo{n&w&s6>Kib47F&|DwuGts0?A%#(NFKo;_j`H zi$V$fNxYwcU{iTjnbU#%?8IRl8Xeka14Q$z$=TWr^a1?}wV}g}^OS2VSb}^5T5(r+ zWPpgE2Z?Nq7^g=Hvm%952xxi_k4`o+|Fd`r`jRO0XA)BVkF*n@0RlG^Z3f$enK1J| zK-eNI zpmKJvC2PRkX5a4LpSs7jF1#``~Z1RESSwL>~HY?@52S8}Gpn#I>E`du0&xY*eI%}$IpI^g5d1=LGP+-(9nVE zGxutf?YM!r>DO3oliIQ1_StyQ3_fGNdVbKuY?6Ri8qeG9e)>wB%W*u6_eyfb=hHo+ zWY6tqX6E&C7LPE1DX?wbF!Ff%{Vc9YW_K=sBW54sNGbN67Z4{h-5NWUC;$5skQ+mI zItb$FtmuIr_nm$zLCoD&9`Wlw^mFnhJ?EElpW;XI9Yx!=P+)`{yJzMd*3LxidKJdy zON+n0;znx~ncFV>{z|sk8Q9U8s_(+sCSI@&yZmYd4>jJL8QREw0psTx@(N?xk>^jB z&ndaU&G7rNB>WC)>!Ray*Tdnb>bA|gXSN`?ffPr?sz)fv;O#T2CC4&@RdC6d$BQBG`sy>C5X{w$rcqVJ?*GXjN3@)VOQU=xH0HL_?)V~ z#nGhu%EJEyyHQ|%h19FC)naMcoO8QP`QdW7^1fMpI26AC%D!FT+t2qIa5Mn*od55u zE2zkpl5(TK3pKlB!sc8~-}2?N1^(|3(lWs}?~ay@u*1x_cjz6#uM-mw&n&&|ZdPsn z!1bFSXd~dd!3{Jmtm!14>+IFmVdH;>n0!A3Cf&F< z)v_gsD*S6u+d3QD#V-Y8{x2{7=a@fJ{@$ct2m0SzVFEKXKMW_HN1s2cp4LY`-)g^p zrvwj1St;+PYZvnh@-Ay7UELO~EluZci-l<$IoEcp^Mf6rg zU455rTX<~sR0tEB%`QyM{Z=w+HY%>QbOj^j<;~q`yX2^AJ~u6Acp7;4tGbulKINUa z=d~N&q;*|RW-HgMYCPGlT+O%swXApce&#oHYb&iQub^Sjy$QBYt2R|NcSNoU+qS4z z`PAt(Jr<8AXSXa}|0_Sac*bWKtEo=;HzccDHD|n)Uh ^1$au~RkI!=_*Tu(nm% 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℞n#mW_ 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

!K($D%DCsFpCxW zL7~YgcA0ZTUjC7y)?}U(c)5N!<(r>ns}Es$Z@@h&mAMKdJ?3;qC~7sK$SF!$Y_m*- zW$IN?<7P!L0GSd`F1x{cJd_`eP zA|JFvnEB|Ui zWt#(wVI{d+mLi;6n!3$n@AYwR<=RDY>F_ z1Fm!+Gz!eD&?~ehxgaomB}F)31kNhFqgGl)UMiKVj8Lc@7Hcfe7iFbbE;JZH=9nrk zb1i{oSWzg+5^Md4EAmZCm=^ek#6CNK5*Ji!l`5}utip1Fpw#OE$2O}X!|#(-DSeGS zIFv-*kc7&ULv@c)RH07QNmc$4|Fl~b%P;mNnQ0Y@N+iiD!}H5MQK={rBMJh`7m8fD z!q;S#mz2_bWFc9$y5|-i7g>fc*7!Y%(<@(p{|f^HBIx=)LO!&8NS;7M-aUHAM-I|W za@Mzfa)u0nK5!8751D4%2fZw&_q%kyWs?u}!~${+%Yi+F4CDZvUi58; zyeoBm2$AIxEeJXq@DcF5Tm=aWBGa@;SY2|FxIl+kKzGP_-}9j5SP?0*jw9ik zBpj0}?E#G*L4$bL^9`C3^46;Rjs;w&3(P)=fs6+vKdz5R(#bE99J)r(1#}I3mrSup zv;cXoj_9FFtXpK(z;!Llw_P&1OV=}BHJ7+fgC#~i5{_omRR#bOU&(Tk^#B8^mbigT z$ALsOU1!%ddK%Elp>GWwnmXS>d4PF#EQe&&rz6Rc4Nwn|BtqAwt85^$Y$U_v86-*d zOn*R}vNWmyAjEv*{V!k~KpoCgH%18_#X&NQ({zS0@MlqiapDFZw%{bP$Duizqe+0r z$%!=yU^*U##t`7t_r@=qOAkvp)8-(Q!(2*eFawCpAql!chQ^ zX303fDGo4#apc2vm<~y%)5Q!#(e%ifW*7h)hj0vi;siQIqlrfhkpBW4j>wHL#X)#v zV>HFnDe!TS#vquCVi4)Uz{z3{1z;E@BOGJT132);?(t|inOGRPvFkf98M_w7V-oj~ z*^iwlM7=2SlZlU`Q5*)ye@TLjNP0$|Hw*D3ibvQ17)61X^qnzTwV_S!@FDRr2}va0 z5P9jy3Gpa^lQ4!a#sTpvO#BFqjfsPg>~Rz(7~$9j=@{EH9fueO2xKY7;l~jeXLy3K z>&;#UWTm1AlZ=cU6nYaY2|PVcoG=-gMm7y2fXN-_jUk+SB=J@pjDi`tEyJOmVV9T~ zAsoeFMm)1)3nXqd83#@<3&v!DLgdVb@h~L!%fJosjAUenX0v#lAc(_Y2%}^Oj;xq? zgo|8_Jg#5)LGsHL!(h!Z}qcDsn#yIgOVKnq6VH)8X$p%RMjAT6s zj=XV*eV17B{UC@@#Qf~f9kcI$_1)Fr{SV$%dmsGl{A&WkFn{?EQTB5Fdq;oof2w9L z|EQIH@ctLZyCuHk{9Q64Kkk+1mlEDRi5f|-p73rA_ws+cY!PwJROr{Q`nSegcYCl) z&>gWO`k?Q=HjXa6bIzXJQnS4P?y@^Pe*$*SzK|aIfj7<>+h3Ql-(h8#FH&;#)b-UG z-8K0vz>DS4?)2|Y-$(gm<}ZKa-Jg=%#upMU>r|MK5^Z}!37CB)S~gS}R740}NU zBlI2w2?&|2wb(4z`l``dYbwQiI{Ip*s!KgTJ1SG zId8W*jpbr}+FEs1^G>F&m+e)fdAeDw)kW59Zcbb4Rde0W8uPi<$+XjTww$+5H>=HQ zr+vE0PSy2%L#{UGL_e|DYIQd2<*L(aXs4%*_GUd_uR7{{r7hQ;)0Ns;x5<@dHeW2s zNHTBJZZwFuSzGN;zZb3Lrqdw9PFL-&q7L>a^9= z)*4CB4+I1GNIsGaxeE|Ghe9spKA7jG@hV(SrV zN{ubaJZnCxGBRJ{d?wP~gf9Mq-{ZO|HeXE7Fr@ffLKhbGFVYwFWP8N~KH; z6slrDc>GXODwT&qfjJVgN{L})Ms7$vQx;pSELI=Yc#bdE8BQ$JSYBr4 zhYU-Syk9;dc`K9{ft8DlvfpQTQLNV$( zS*$%(B$jWnQBxMgVuj~P!kL&^G@jN6dRwawNC8Vs)?np|n@8 zGF?V_dLRn=ekM0q{;zW4*WdpFvJmoo)3ty{@gU!aeP}@B^espZY{&J@uIKsChmPB) z?{O4tK?wAa4=p;GA}jQi>!Y3zkqdzfbdQdtxR_`82Bhc-89*-jo<}D*z6OvE5b)7} zLUyJPJj3=Z2n-znw+D%IedGZjv%x-Jp=YAE=D5hL(q3@(4%-6G>J~vfHad7+ykBqfYzf(BJ?%aA-=kv?z?@W z#4>)*^A9l4Lr|j_DupzA z&^KH^Pp3~D9Zp=7oR5Je8jbO?au0uOqi z3+U2y{jTffz^F+dMg$0@)gI0+Ib3BqVFT6!>^gwZrS z3XttjJ%Gv0W@JW+QIKMgyc~OBgecC4ogqdq6XZn*#YbrxPRCgqdnro&elUtmEe=NU z5R-gN7UOU-CSd~$VdN!=>4jqqU!>-EA8LH}rkQp3PWc;p8sLkr^3EDqBE>h27OAr4=nNJkJamac^% z8Ul0vu~}vXp%>6#z#Io435O{dV?0P=5EAEz&%op@&IyLE(95iICK-z?3RS^JqUvoU8S2fnsardowjqj+48ixUbZt$ooAW8(Dg-gozds5 zMV7S}^L2aOQd>)H)7-2&i*>dooT;1jYN4yGMN?JJ_-2h}V>xe~YMV`aot-u*y{x@z zx3V^6oNboc8RKlVrj#>HZ+Dihb$hYNTCH}YvuJGAS+h+PZd%%sm~N|N*s9r>Z#idr z*6g&%rJQrtR9nqOTW_B>&pBu9#=6mLZPZp{wOn;Jt44cEIwNzmh1OiCt%(@{xQb=W;*nwp(^V zI5!~~ez-Lv~9(a^sL-?_)! zO`P%?_;vMoCyaPA$NCMA&!<}c+sIpx;qJ)f9U89QIeovs19rO;Gr1)g2xZZw+?6>FnH#m1QMv&dN<$XlRUhB6y#dg*~xctuoxf z;S;7(uJx;;$PzvL1GS~c(cru%0r=4t^cw7RN&c~P<+DkdnJLBn0=Awqyo$Cmy1eOQmUfFm-a-i zUwX{5g(BbnQMtIsE5FCGwcqQ;B=o0Erp1xvDp%NYMLEiuOU(XrnX(BV z%7-Q85k(R?wN(3y5+^?AyZij7s^THT3PRy=g*REHDd+-O0kI_T98=(Bj#mmYTQ2NB zVwB1wvBV3d$^rXOVwle;%EP@%O?ZA#;%eQ}q0*A;9Jl!Kk{}mrN~3bjF&`7TufP8V zlOi))z8FLl_d)pq@C{ef=sOAWp=Uw>TuNqh=oJcmxs=yM#kO+X40>J1fB+hRl9>SX zEZag*_j{DV=1_Rdw``~9z?{NHG*Y<7Bj2|n9O$s?kg2xq^eHbV2YM(y$_EzEK~Ai5 zdyq`>k=vy-Gw6dppfooKyRh4%WGe&_@*sIzcO5fls2P+d=XWVbYYPrKB%&?s<~vBU zdX`NTdX7U~13Ee1M?MYTwaBCH0NW;ML8eP#I!cbq5i!bgGkj=3+wz6r-R`6F5=m}d1{$1uRag~;?Mi_0H?uAdX=C}Yi|_>^tOzx3dzwj3Lyz+3e3Dg9_krfQz{J|zW`B$DCeyluHYFg?(xuvOIwZDyyo7dw;G%|bXjo{TJK8pU4Z;u!=X z9vxxbC*N!_BKJfz42DP800_s?Ec9lh$qf5x(D(5mNWd_J_Q(qzoG#3Xd5my4!lpk; z)5you$V^g{jHj_Zo)3nxkCFc(nnqDFO6-{v1~?7k5F`MDF>uDy2qzfh=@7ao3X|y! zA0@-#vFoPff;U;rFp5Z6UWCR$h!SjtqY(K+9Fj?sQ33+ZOal9eI2w8xKAM1V7Ml1t zoM4>7xjCBH7^J2bjprZ;!@2u18ciWaX)+Cx0SP*UFG1$NN8@BTP9|W8t#pFH=;aVcn3DIm1GO|vuKXv_Ahsq5LgqpmKwZkpO!Y^iSR zW!B6Z*>ZE*(wFV!Jkzw!Tx%>_i{`r1YHjpQ;|A4D*R<7IJ=M>-Zp)V1X>AtzveVQ% z3tIKrZs>FMlrr6x>Z;RJ^_AKt51n;GZDgnGQ_6H(T_w7$+d0u~-C1h-X03Nxr}K7} zsjb$0-B^;-jVnAiectTo%beym*EgM3r`c#Pbxl8|UNttVcAe(7QBUWqk2r20$v;oI z6Ii>Aj=YYRb`_|(kNdRa(k;w|j=6#aojujxzSi_Dp+)lP|rP>%MLK*mg;Lz(Z%&w zZ(nHo7V@TZcZGI2_kNn$eOI$xPhZC#d=sa4)ziMQoLrs!I`r-hd^!7_$CU$S^y3Vt z3X)uMioEjFm$(8~;yH;ExvIo8_hU{1#eyW18SOx38Uk0LFb^j)Jdhq0YrH6yxMy6AXUob#nN=i~;{|~c7Cf^jmgP!S z6vTnV%S>35*=AKPJu5IuqgjaSB2$*6rq2}%09rt$zhYJ73#A5A;22h9WMQu^@+>Em z1ztMf+ALQt3QS4Zmzy<)W13=x$t9^N^McGOEYFsTYEh7i{6W0{%GFM#QdAU%Dah4|z!XHGO2)~I zXb^pZs1&+;Jg3O4C~@pV>6v1%&VKPZ$ME_l0IQs zMV)Jkb?#7VRO{8fs_^o#$a2M&u+LV_e?@+%jEje@VwrCqNp0;Q=cG|M4A?pJ;~>ZP zJsly4JU~fKzKc9$K@YhWFkLfe8zD*%qr54I@@h?=(##O$bCDNO+W-#HrujLVW>QtO zppjnnX%QjO?)aK(L8_f%EU0e+zu$Lr%{hGv*g36ii${4Daf?DyP@~u#bWMA!hJrN2 zGYWS>w`cp%>ywZBv_NrSQ__@;D6h)3yTHmzA;~zCa>{xZEh2S@TZp`CKnj@AQp+6b zLrC)}UCIQ|asZj7b#uO*Php(Ay3@9DGM;Zx#LVwIuH(8}<;c}6ngy?))3I`OKIL~A zv}o3%pkhyhJy-W=d8O@{4(ts~ip;rrDJ_6b-+_I@vVm_Q8V{L9R>MRt$vZ`!$UhpN zM+54St2y7y@3{k;0!}ss2QBD&#CP8^G>SplR6)-rZ)zSL?O7CNb1avn#iCW06eb)H zXCYZQGykY?#uOxL2n`5K6XZx3aA003>rfPuTA@Q7OY=RCf`D+Fy)LDmZ8>gvm9XJa zj1JJsP^uU}Z_7U$r_zGg9=r6*85m7*I1VA0`XfAri-l_qms1!e z(}iP^$FbKVj}T9y6pc+kNK=$xpL`t!IQ5JGnHc*Cbn!67_INb({Ulk0*zzHHaK>mb z!CrzejuR(>z}BO{3rAx(agzv!ZZZKe5$sPwG<^}8N5qrf$P41d1jT7|jFTY5AQ{Fa z6l_Obh`}%o!U*EPMPbwru!?90C|5@i3m?IGh}L z5L*)zMUEGt$n@|$oQ~6Bl8iv?W8y%10^HE^yb}@^#&F#8rv4;}o$NTU@qkvvlDjL2 zg3!WAIE;sL9HH@O?8QeYh{M#6#xIY&Fu_OUMz+zAM4KML1u$Y{xd7oYJR&KBR)CL^ z2w>X_XnAK85htS{!qCTY&m?ZdcpTzz2os1=;<-2=iSryU@txV&MZiidG!EkwC$$Y!1~?ea#*o6L{WyUMjv^fR6D^IxFa+ctAS*kD;TQ&Z5(lVf zksIV3^!h8_`yaf!@4Ox8bqjjAjfcFUT%#JDL1%X|p1ucT*L3ZM(B1@CyB@H11?0O3 z;5sYrOs-XGIUfH+b9N?lavF|}Y2@$hdZ;55irha;QwU60S zUD7^g7sRrRQmL}+qLbPBj8>*!(8|=!TG!{Ntp#mkrZwixrFuasYb{zt`(~LnT3b@t za1X27&HWdky5dh0nYWyn8!9$Gp>{+>2ZEx9i%sll6;G-<-2`Wu#-#Y@I3Y znY+_@hicQf>c2s=Nb)mydzj2TH)x!je(PpzSG>3oTferP=P+6J{c*N-fg)RZb%7Gy zXlZsE5PRodB<5uIpj&9r+W>p7myua(;7Jib>qP_Q?XlXK^@cXrb7-a@WHaM!7YIfO<(FbUm)&=gyY$V1nUPRFsk;33Y=J3(|n-mJ6Iv6qK4RFwg3H%=ADJn_OLKw#rqZ z&p%^oAD6kk%Cm;RH`y9XOIn%3YH_bosR^viaL*)xDU^v<9Lp+2uAp-3;?u*=HdKk& zuap?RDv0|9p`bJmL{;J|hc6^f;6*lKnC1hy+K@`zgG!4lm6#I$p!Dgd2Le}OB#u|* z%5$Zz)|pg2s2wsQi<-6Kj}DYaO1b-3{wM$C*OUU!f2yTOQdz8U^(R%KQG7IFZ4!(u z@;oEfc}WzNf~+b`RZ@G0%syKbyr%L*bY$hR(`T5*0e6fZaZH&Lg_0yZuh(i1>knn_ z0sFl8sJbWcg2*rrD+*t>$n7D?)nZW;*d{AHFFbzwlod*BMJ#j+9Lp7DPTp%33cS!3 z7@^4SiGzJ%zdd`v2nr`M;vb-3Vu>w~dyIKf`v$|-YXWT^ zS1ea3_sp?esQa|j7A;VOrVA-^Y|AU7C{EY*b5w`E(o&R%_P*-+d37kQ<#Q;T%FkPL z0RSDJvX3Zc=Fom>a9}`xU{jU8Gw>WbLjx9YtsHYhCM{Q_eaL8cW7nW4(bjN}%+t>a zab&2ixf*b6U8kTCMXz#j%W}^~Alm_u0!N-tp3;&?T146d7DN`USws~1+G0MG<3@43 zylWcDnNT@}3)(LIibAov0V0E3!|wtIQdJOm$fQX?mW2iu${W48jtg9eLRo#&rjQp+ z9mU)LW#Kud@A)K3m{+-?9LOVH8p!i(Pa{JSEx#oB0JNoPx=oHJU_3%r1;wa=DpNRMDb9v7B29Nyu6jXOH;ZV z07jRx{b;i{=ZryU8YLoYAO1(bdVfZ6qEhd0Zz2ecs_g*Xw+OFt9j zU^j_ki1c9UPH`5yNs8vq!i>iFWq|Q8oK3@I1QGUwI3|f5;KeY+RtSgwEE*qCVA6F4 zZaM@oNx~`g#{nM1IJ8}iqj6|Q(a`m2YqmiedpMCWPSOm)*qMbB zw3wy-1jlfK(KwoT#O&}m!L%#dk&n|E48j1|P7uTsqT8RK#5aQpQ6Aw4(Vq;)7$p-7 zCfLKHVT_~1)uB0xKmtHwj!C{_6FH02x8~jmfjIEI=`5sJ6d3d(I7uv(0>CnX?Ce9pt;dn+qZ@)O2L?n3`HYRE4k$~X{&L*=FcEjie8lxnh+payF z2Of^YFdPQNF@#5W;?fdM#5^JZi9-w&a#X}2codCPoPwC4Ej{E+M){+mWCpdEhoYEF>-UtWt#7R7o z?i7&RM@C5NR)bM8cJXMTql7GlmAn{%1SUgFUQ;lcZN@2#j%GL>`r}E2Lu4FdJaT54 z@5i%IVno9zBA$8|C7}NMAH4e?dT+@^y99&a9sHq7xrBkD8*^_+WyDCFFUPhAmo4y2vu;>HC3`t#_54mP?A$-7Cp zyOrd7!O4q&?!pO&=MQIvs8^b-jc$y3t@Lw)=l)!!72bmE^c|4hFTMq2M;_mUC`5qC z+Uw_oTW9pkF}iW5lXoZViv6qC^_`8@ZpxcMM{nC$?f&A!lRFQtPkUXf zvDaMOw*I>1`pFHGC%2woo_Y1^!$9fy8yU(%X zv&T!e+N&$)ugg7av|~he*qb6Het zqRcd&*A$laIum79;GXc3Qsg;7XcQhw!m=r{(gU{0R)tETS(J;1qta86d&H4LL1n}$ zzt5E#g2b@}S>`E|?8zfhWcY_gMc^EsFACBZxjHW>PfG${IuMv9WvelgQZIg%;Y5y+ zRHa_#+MHMwi;PmNFiN?|4frA_@x>=n@kn4RJjay_1)+4nF=D@8JdkS@R&0tYakp^5 zbqhRSDm{>xC#=Sj4|@W~mpHL5t3sP&8WP8`Oo`*!hYVXT)s^^IFzgc=HIOMbN zp<+M$?}`k=3D3yg!K?dHDt8oBA(1oX0xHz^_SyY?o)@@hwQ5=B4y%>&#}uW>7Ha}q zVCC;tYh<>J=u0rND69l6&(s_;-$8jZeH*wGy7C>`TaETG^DIbfLN!PUVi0seZ{X3sYBtC# zG08)h7A-n-R{;wk=-4{lUcm6T#I1ZwgaNH51+MFvXyEot&+1c*hiafu5K+?iDXio> zWOR>G$N;d(fG+ZU>WK$U2>Lp$g3NbPa7`WPTkR9WecB<7wmx&+Za%o*^IXq{ zv@~_gNAoSmg}t6*+FbxV%`+evczW0I^6crrpzYCM{FaLK>v!p<4HS9vw1K8;CIGqx z`yPp(Odr@?cQ7zWrflTUfM`*xL996%El{N(+5p?CSVi+NTI&r zY-aZZvM#!dBZP-x8ip{!!El6ZjA2ULj|1OJA~Z;|$S2b=Hq$;H&d8rzh@$b##bIay zG@aqZ@`mw<**b?9YoXpF|` z(UknHq(KBy*Fb>W6ebvvwS_K*aYXKjm}KlINrNN^`ZMBN=#5hCrR9#ZgiH&Tl)8r& zGvJMf9-O+F_j2kRL-Ya?bzyRjp8b!(`yagf760ukIj_rZ2<=Ld-|MO#&&w74E04G2 z7MYIXF}oUrUE)`id36Kj8jY{9;;wn-je_d~Z`->myCS=5uY#TU(eBio5508a7Ic+t z(Yaf0USep@xuV{UA-5XX4e7X1l4~7Z%UG`KD&g&N?oRrlzcqP2<4n~>km2~w<-IPq zu(IL~tn3%w94kX%9KQzxAB41RTH|!HCAZC6tHo(MTdWt_W=n26+oUt+wl#Bd+tsFN z%jRa&S*+WcwraLdH}lnce%i|B7cJ8+w&>inw|jJMmRa62O>b#e=xrN)k)57)=BviC zm2cD8Zk?+0EBv;_rq!UkhN>4`)0#WGrnQ!fw%$=Mw(8vO)VU?L=@&b7c1V=-jPlyl zPII|vt!dM=HSL*3xpC($(>9bYHz!t>?M&Zfmm76nG)()!;3OZ(|DWXzQL?w)#X1R2RCP2OUjuuyD>2P7Fcu-l4sltq?vDlLJsa4 zY2I4To!KzYO}!27Y22yq#+Y-}_aS88V<-FXQ|>@lPVT;Za@VxmGv3hkGkEFvIESaM z$u)TB)z#s*?e6LscZa;X*R@w~fk58bLGE_7?aq-GVBFg*^J|u1Yya};@fIDUpK-*> z1C}YWN|`$-R5_XM;mC9R=lExp2KSH`4qmdAhX-s^I^-M0(!R*=m)R~;msFms7P(rB z7bQj(1+mZ+noOxF@COw}mSnlX@wC8^D_3Npq%b4iV#Gp$RoJX>s1+nhFBU{jj6|~} zafOD!Q3@GDcYS0fuHL0vM7D|y$1yx7H^gpu|+{=r6p~yFFX(qxFS=MS{$cHO|Hy!TE zv&DxGI-R1#GW7$o(rlKhe3N_l=%6ba#Tr)?l!hWRwY|?3N@6!SDAfo2LAF#6pZ-I) zlzl?fGWD6#Qx1z<)npHNm9Gj6-xZ(gO!_R}?w+m<-!f>ZLN<;AEK<1hM%wMv{sRu_URT!k6}*va-Yq`yYQ=_!i}! z0UOf&0elKw4e}DaoK$Ah7V`)izSG;bkMGfKBmv4POF7%gN667(-^r;)zGKoh`49rv zF@5AB;5+oBk;*2r0rT7Gz>tMP+}LE?)nBYJ=^R7Xi+51r$866II#21__X8MfFgZ#k4%e%U>QEt zDBI2^zHI9#>0SwlwsP})3(&5i4&5V^!dtHGc^)m^bh?^mTfLrXI{D_F2sjR)y9AK8 zClZ@x`u#jW2)Y^=m>$uP*Qw_1%zF8@q=@c|K#NZEy*yFA$t6Nv&4D?{NWmwl>l*Qf zj0eD>yLVd9qIX0U1lm0_rkj^y5Dek~JH8tj zao|R?co;|1065t9V?T<$Ko2RV22h&VgCz1`9LC{rgq?JV$0K_@BohPd59deISp?BE z@{;5zOwi<*P7AOZ4e5RZcsR>~5J4~WG5I42K^DZ0XV1(r9>Ylpv7RL4)*1tZqv6rS z9|4orD-LpGDjmDYFq!y4jGc+Ii10W{@lk~R7>(=zVC)hHN5M-!9@%j+L1Qv$k`8?* zwaBeyfRk(r(q%GBk}*mwj6?qfTPZ@xOFV-y{@Bob34(-nFY{(N!KOtydMJ%2;WYE? zfNtLqdS(<(tT2t;qi~9YWP~C-OQK1X0v|+aKpP0+)CkjHJn{qhA`9WbjBw;3!w;w9 zAedn{CVt{20;qZ7kpC+;Aj{I{(?3?lXAG})# zzehxD3yIucbon~I+4m(oOD5l-o7PPj?UtThm8>`9O&YpUxrG~@le;dVC9oq&7cP13 zJ;u(@-(L}G-%xpmx6y^m(WyHLZf`~bySZoQj%&BXy$>b5g@*mX4m9jn-y97K{2+M` z1}T7-dv~_ic{j7wMsKUl)w-cxG&9?DXg9OvMn7w3w%PVGYj#>4b=%KO*RE{cnfEhm zUZIWM=x0XzjH%bR?!3YrYd6mOnJt(3&Yg=*cD{4xV%?Z8PEXZUzH?{0v!UEEqW*Mw zMjdPD%T}kAb(XDpV>#~-L#xhGJ7bP@a^l#verApA8gFb)tWv&Mr>(cMd3#Rc+GwlO z&PMHMoyL5rFI7q&+iu>ew_BZ6n>Iir^XfksaO5NTNOs7ZZ{|s5H*{vaEpm1fQL%F! z_EmFN2vhekp6Dq3dv5KuOYz{+xM5t@GhXrR-ZIkbnRt!oH%^!rfxJGSy}s6OTe*pT zzo#3fp_@A0x?pf=cv}!^`I_E8S9{?*9cxe@&I6NQL8-6eM!N{v&EuDT(Bg@<&AHwL) z34IC<_Q=Sd-_i2Mc0H}rxBWgXj?pahHT!z*IzEF>-WF23i3XkIC6m{9RA)o79iy)Z zy?l2q=G(e)aqeu>fRk;!H}*=nw^H==RI4+&mC55PRim%ZXO_LnH!PsYTXviu(ZlTI z3bkwt{$-a{qE`}3%RNtyuQ;4#G}_}Fs?73#c_+H#?WL0~?e5jd$@bDauU;LKRi_&A z%FknBo;Y!`oxIhPog8OpMXs;5bMiGNLtbUMxor{fabEOGrc+bLM99G_s`}(4N7?9S zCthUx9Lv)kGFhf3Dzc==%-+K?!#!rIl6=JR9Dh(|OWaeQmh-VCrC1eWQIeWvwkXI2 zmS;+e@>ruxx^mS8a(%`R2G{}t|~t- zJj?`EC_X5NLch?FD-8Q+B=Au~{G{+i;%PIt65B2n7=~ObHunxxrdld_jQq4CvaG}l zBu@g%*NT{l;Tx4=lbsay+ed8S(Z1ZQHj3;IO?~8x^KVuI6((03PaU?uglz#tH z|7ZP+rN8l6?HlTE{z>WU-}vSq6q&#MbIg(Q-jDo~MWwX*7k>NKe)8Y>R_7Og>W}}W zMr|@jdmqAIeg2(4ks0Y%&@a7w+T^mvpMCCIfA-tI{;B`^8|;7bzkGR2iD{;eJm`23 zct*~gaw!~R(|raU7m)A5&?TpQ$Ld1>J-M6__zgq}m0aa}T~PfH*v zbmzjHux61j>25yX_RlI@b;_mdQj!{=kq`RY63Dzi8r|K}+48qQpN_ME>-jEi#ZL^H zuI*DS4UoVFB-wQD0H3nq zaukuiADbiuyF2LiHIs;C4*I=bx7!<-mgYF7?NG7Jfn__E?zom~Y2;ndu|0F(rbh(4`r=>5Lg?{^25rgt^sq;A@lO}w#8lXz*G{jM?SS(d2} z^gglG?e%OjhG-+dEHb1&pbwVW)9h~Ecx{BEv6mpa17!k8)?65cF^tl2GQ`Oky8!}j z;J70kgCw5fBWFJIV`~&)f0jlV1{j5bgT`j$;v^YU_-Q;#A)Z6*8RR?a6pf-_b{vgj z7aJJ}6Oy2*>rdz|mkEYA2oi5N4`_3G6h=uf!;$S}6O4v_WI!iOe4M7v$Uh3Ol?OCU+cw#Y z`goYYiD@T}8-ziej?&R+7J0f0umy-I2P2AECRm3EAK@e%9hm^nGd%2rp@(Mk7~(jL z0ZjyUwGbV7coalV5PAL-PscF~y;%Zr3f+mF2EG;hK`<>pMK`@AC zb9dpsw0%1c#(ofnp&k#NAs9P|XzRJ*%fK3@J}?p#PW%XkX-ZaO5;%i|j>oep7-G+k zDbdl1ryjcDQZT*o*h#$D zNqgkaYA^+^L4mnpH^V*(X3kME8lLz`9|J!CUW#nZ4I?wqy=0d52Hw~k^^yy~E*!r9 z!Mnd3zae0Eg_?Da&Ri!$#Wzb0?*wJ8KtZE(MOW)3-vZ~`T{5~8KDu`!Oowh;@TU78 z=y$hQyH{>|a1Q9@sTy86aT`W^jm;~GuP_CJ=W8?|V%FZnzyh+!`5=LH}Z{ zde_If*MQTlMeoA!oe1NQ+zIv-n%l(;x-z$ryl<+vk-XVkAbDv>&V-?#GM#lNTju+L zu2$_;r?F`3tGRaC&gRR-Vl!Va&pNlQwE1eCEf=j;Q)@OUzpc~B+qY$>>T0>(=qqix zXf~GZ_UUG==LEM!hjwpU(DrRD%5Yn+PaDgPzGyYH<&y3S+ELeyR!duK)~jaL+??$S zx@l;Oc8C0)H**xP(aAD>ooStmT|w2Ax@cvacBWnI3fkV#%?@b$Hnr7S=bM7AwVd15 z$(yz{v`uHzZtJIK+kviV%eJhwR6C93LZusms@Z%)+qr4&rbg6s)Vbbjs=xe$!D2p= z|BuKGP_3_@5xq1DwCK8#V<~>W)1%Nxr$3-)w07U{bc3wTXZC%#i8lXl^+s{id&z0*Jp$&E*Z}wGP zB)|d1%km8L&J7ICnyZm)JGt6{vjx8T*TF|Jj8=)9HGjLXbk*b)Owhc3Ojpu4E7{a@ zm~DHF!eGbQSqG}^#*rt-+a_7ZbnC|~J3gUMM@EjwsqBPYKRG^m=hg8RU?FE;(LExM z&lprEuQEFH_?=f<=;I{IpAk)T`WBU;PqO2D`m1eCUp_TQc*vz!TL>q2hSvOLSAd%> zl9c7Dj?ai#$JcPES7(EAyk@)2B~^G14{d#X=Mp!%COLpZFQ1dxF5osAE-kPmq30!o z*%_RaT|jpiz}c(wmS~rq@n4-Yy0Sc)Y})0kR2d?Nx1+f3Qp~y>6_%Jz* z|IU}b`L*i57k!gs(U&5TdtCUf|LTAEYk%}P;}hS7dwl)f4`2QV&;R%AD~ta)`|97f zzWSBkzxf~iO?H z^1;8xee%USpZTqf|D9;>hd;eG9)9AF_V$}X;lmHV`(gj@f1&*Q>u(MI;KNUvKObQK zmk*x}zWP^x?C@~-^5hfWbv}Fa7mVfJZ(6^8T3+a#Z-47MKl~a0)d&CUuNXfI(Pxu> zwf>z?{rZFHCwYGF!|Kof1M&&r*+2U;_%~7Z`SEYBUj9=3KTo~i_}sHE{$%mfv%j$V zaPPOufAg~)e*A}D`t16XfAX=?;A1Zn=Mz?G|Kt2=`jub#hyAY=e&-MW!N1$sE5oSs zr=!ED@L~LqpMQJ**SP=wp(1?e|84I}ej{1(^K!49#Vi(^#U`8GRh5~P#gJA)ZY{?ITX9QRXgXNN3I#>p51GZ20!3*Xl>tsMMe2^}_2y@cK|A1g0 z3}1X5|020>O}^0>n!^jc*Gy(cMn)vbsPFr2Uw>qD5C7aRv}#MTkB+dGH_zq9!t|3LoipNF3xeXBUD{&4uM-EaRR!rtBct)r^?o#>P~YLd<5edqhqH&*}p z-_3vYqj{me{^R}M{5GL~Muc6S{k1QCS&(#H6IERuj$~md59N`jnSwGLO5$)h6o(?V zF^mL38V&_)lTbC-JT(bl)5IZc@uDaSLlIjO3`I}`xBwq`aA_n-;z)wyp`yVfbVU_) zSripnlX1|LE-7$cwaTW!SKCw#9WKi_yht|{RmV5$vW^SoE9%fNG^|Uh4)NeHx;_$N zSWUMSU4jt|Q<=ExdK zk|qixZKP`oyaY|wElY$U4IKuBTSd4PRyI;bDt@*i>#D8~@lp(I=@C>JF2D;)&>%CaXh165+KDm7%Wa7X}zZ(RD$=)v!!MhB?5}4ShJ&O-sjSC!BgHnW`nq zq7EPLmTg%>1LmWM;z+>DQdJ4orb9E7(NM?BhNlZdfF2V35HuNHg9boEGc}x!YFh@L zmH^XKR72L_$6$(vA?o5t6*X+6GKcV{MQLc+_7L8SrQ?M!L@t`yE?UIn*bhR%9tkrK<{PVVtk{|x3{z`Zyr0^h9S$8g ze2=Ecv5JB12Tp1Q<`nr>YADXcK!R<0K@_4Qo1H~wkxr#Ppq!bAjS#+eYRI8BfZwt4 z)N#_l^PDt|;=sotTfk9MJG8agdvD>|@2yBnbK8`BX);4LG6NkYRv6lnA0p%~+^iIq z7{NM|VB$GqW?Lv;IDwAK*&~E-#k3?!(*XJUnGfH@UW%N+$%9OdP#i?D0S`_BToB7X zjm}ONC~;HSL+K=P!*sS(oFp(p$1BE`nfYT>cybt+IGJ&-%c?hxuz@r11C&OS05-X7 z?uV&shrSbdNocx4riGzVz+6IkvPe*@Vj~ZHn@7_mHPFS@r`AK3_tU6=$0g6IXl<#Y&RHZk&a`wOg~N|H$lFgq~_QS153|D zNA&_@iF9mYo1{~3Y$JbW*+J^XNjeUE=)dw&6gyF58U{*22VPn*oy$R%x?zG0EerzV z%s@*tw(Qu{18fNl!%!N>VFXf)?Cf{w*up9XrddcK5|!8(_#w1I*vA-WXfnT^e8-WixH_d} zf9{46vD);`J2*A4Q^<0D-d*?C{JJM^i*;|gT@N~|4i1>=^q0%QW}9z$98uL<^L%Hu zhVz5Yve)nQ`E@bq2wncX+h4A?Tj;my;`&;BoH)4duGXtnx8Gk2n|{77`2L{JZ#S#X z`FX!I-JEZ~GH~3qCnI1Ul<>Y_Y5HRcLCS-J8;{votLG}+@(2pZob97 z?nO7`7ge82pZ-1O_K9{g9^6_I(Tn;w`Ndd^t3Z&FMBzVolB2mA-`Jt{**Tm(Z74@OwQ8eA)#(b$9tr0Wz(u_E+u5IcKplRd6AlUAkDeN$yC?+CT>iW@dbma4bv^v+Iww?bD2yWKWb zr5LW(uIfaa*{`+9Mym?bX;bV`{eXJC2b+>bEE%#@-8p~@REK7zBf4875{@Joj%hJ9 zk|T&^z2lI_)#fWgps0S6=0vU|6OAs>95p%|bbytg;5!JKpt{69!4m9SAOt#A&B9Xd zw(h8^>Kd@)l^GZ~4FGsXf(-x2z8!KH|PWeBug%MB;qaqz zDvu*)l80zD&*xZ13SdP(f1mkFJ5GWiK{_fNYaaXIGz)XzGj%|(xUMjOVl-dOgCHwL z@o?z*!PJbix$X}wagL@}K&?T3@!JdH3a9;t|FxfoKlt(d%`g9E{^q~``im+@JY5Ii z+V7Ix>y&9v-0_rO31h0qW40fhyE+u^ zZz-Rzu^Ld$cZKbFuP-m`G%L*0u0_0 zU`8G`mUcfQJkj01@xa5DW4`vfO1G#TvO{v! zR-;W5EJv^;`ReQ~al{N*imkNCJ-S73bbT`Ha!dou_tG_zCfj@FaRX-8Y%(N0>@sYF zX7_g4BLIEj?tq{>uT`38@C?!XuuqXBL+wblh+>J|#;Z=1pg5Xm-?3b!|C)H6a{E;C zSlMT3>g{fmCdg`|NxdQ4^y@ZPYXSVNkhS_dszGtP3`w*FjHHrZtAOr>&CX|{IZJp(d5WBUWDwY!UL)si4v7{fWH z<`|YG<4j!Fkrml6MQpiNMR}x*G}F{@;GT=a^*psKU?;+kWR$K%98zfG2uBO6tKv$1 zj)YO7WjdDXm6^Matm@F&v2@K0QwTbgU(RALN+Eq5s6bY0W+Ox&le3kMfQj;X@Qp<`m}w_eT^F4>ap$ew8qOK9!7 zWeB9@n1bR6un}v3p>gd#$HD5au7$NFG#vo1X5t7%-2}9N6>Q7;b2xz)3uVAcaNRr)VrDNrbW#p~-k2&ocXcJW0{l zb0qvb6lnMacBR$s~?WPwh!D_59PcKwe~_Fe&^P&F4jsCuU&H$0*6h zfl;6YrC#oQi0phep3UL{Ege+E6I3Kl;Dkj8Fl<&>KEmbiTvX`J6a~@57i}wvqty&& zCnwX`K@(Vsho=H(zy9zR6Bu4Hfq(U4 zCJ_1I=Z=FVJLN5|mA_r**b=$qSL@yyQ2zO*;PWNU+XOVe-fq?_ex2uAz~=p;KPdX! zyxT7Z=PNiRY}b9EG+qvRGJy0x5DK}!S+2L(eA&;j{j%sT`OSvEwqFWcd4S`xI{CWO z@AQO0e~`lfm-fr$b|vuZeor`G_gCA^_S%M7nlQIpVbD3pDgeFSR#^468@U+t`n|8r zm_MiO>7>FE);^uEccBda05v~l(UfkD_ADv56`*u`0{2kD}3gDoY4JVS3-ej_bkbm(Lhh5^|PxdlmpxZ-8`XF_>G%Lp%=7^K%NJ$?_r6k ztC#V3*{$odC6mB=J6&gRvKY&?nt#j^$DILu2Jp=a@v2&(De@IZ9a2rURwsAqMweum zrd)0967}PHg|1a-lB`y11leNu4;utiZLvH}G&?7aI?3?|^*!Zq_ptJop_`o=0UV*m zE-EK=j$w9dGyr<4+Mf36$2--J6)$6`4&4)pU55Df2WFQdDZaYfQadqOAGLQxVJGkI zSND!;I@S2||H3rh?(t0Vnu>mFQDNw6muR&+Hm_#`veljK>>U&=-6M$_-yzza<~y!h z>rsb|nptfb`$r>d{~v|~+unJ7Cba66hR3~jP6)D7pT2F7r&Q4FHNUr4VQMnG8||>u ztt4;h4y>zA&>TTh-)~Z{Uy*dZOEHyJV{gd49TM!QwiE3T%zx{&8%m|lGx1KHWB0L1 z`}hMzRVw&%^PoayRFymE*L(`TrQdgJg9Bacw&C@hRB7&{T^&?er*_n+SDFD<+f#v8 zs5-!GoVg=lSv6b(2XHYP8tw}HY#?1Yl}wft9hN0q zwyu=YbBi?4XTi+XgRu|D+KM78Jo7RXOs6PKr}HrW08A_L!hC{|AEo12A)z8oKcLxo znx(ADiKEYCYDMy)BQ05l9Ksa z44^(l6Yuo1D43wdBty7Rw!fN=BR>jr2aPQ)OK?H&@f0mlnrAaT8UcHXW}!EYVJfp} zfFo@3%uG>i+2|CQ$t+4l;33FIk!8#?6JFCK61`wLLus&#f>iJ)A1nzNj31$enR$~S zK%uKq8Sa@*))M@Ub@pvx3 z|CnF#k8=k2$N!}MD*k|9qK!c}RR7c&yr67A0&pt{%I34SeLh`(8$uQo*vbV0~Ba;KB?f}C&o z{ypzR2YV;Z*VsK#6dUZISYZdncG=J2>jo!@hyOAp21yekj3Ks_FFQFOoZQ2boAhaBWC z%9hJw7Y|^vdJUg1uRg@)cNoLX4uPm-C7!WP(b!EhChtI~Tcw_h{p23P5M|M84$Grj%e1~=QSwrXT!zgnsHXog7k z`6~U*>QS#jk{y~Qrwww4tn8D-s{z%lHkH>T*Q(Mq5ye!KV4DXLw{!ez)OycQMAzF_ zMXJpb?SIncUhVBy_ZLxzX)~2~9(<FIi9=qQo z8g02(VfostTB|xDYQJ8mXyUlH{=vJiwT_q(^@ncAktEAz-=I6>9v#%%+}=Lj@T7f$ z{=8KoiVE{@582k+xJkEWo!tt-F864PsSf%24$gWa^D}z0FGuO_2Kp(<0hcu5w89uq>5Vs~>e5wMOf>+TQKGsgf0C=Y;-^3a~1T zhMBS}k~pNu{cde{ze~59wMIj4lPYmgt5z#y>#$zyGE}8Tk(KZ8zs8W&8m_Bqie(W^ ztk#Y7dSt_b|5O=pvY;u3rrVYTp!q`c8(aQOY<|bk-N3a6RKam&$I)aR*CJK1Z34hQ zw%(VK?7%!E)3Oaf>AEI6nr#9wSBIv93x}GeyZa0Ex;k;hJ(u)IGQQziY;E~ zSDTtUw6QQYuJ36BUm3ZkV3{K6AWBa6pl^R#N|<4#nv1{DrK;- z3&gP%QB)PnE!mD^mlYIrMRF9atQLeNj&Oxo7poZK*CJwf128UC6%M$)wfu%VLkSj-4aJ32S`OvU&MAcj!ZY>=g&`X7RO1Q2m-ZniA zbBlRsh0aPFrwah_V>=40Aa;$!*ZdfL@Z<0-R?sZ)kQ;x9r_p%f$oABe(nSbRI7*R$ zVgn^-0NT@8Hnx#x6q%=F0I%Z3X*>zz49x?7f%G7lg)=2|+=-7+50Jx6;Xh4_06Cg*?JddVDf^gx4<-|2lT_du`j+GR^ zO=ek~dB}0EZ> zY%)f1v7)(mptGR zf7W=&BYyYgJRK==Ms7#+5sx*uoUHUrDC?HMV{XWNGaO#-Ul6R40}jeqsv?+^z&y9ayx0YM3soNaRK&Kczryx#57hp*92eZPCe zR(9AUrtAE(ceMDoIHuD$tnD^nwB~+n?7xv(@BZ`aYJ+@h)fyF;(+S6Z7$4N6{?}LI zwDODJGo>~#8;T_V=))Vj*CjYW^lzv)yF`^@l#}`a$B>m%a%TzaS6KKQi8&TMc}>6 zz|mA#X|#-4iju@sEKkl&?;(ji*z8<|kw1jaLaW(kzJl09WM?Tr@L7lufgxZG1$@ zWIW5$aguzTVB@=q$IDsC_$$Q@}10H&2nW1JR%9T zWeg<50ID+1tTZ~yk}3K)i&K<;2+;Tga*7#3u0G9+Fi6v45`|to_S^~lyv9xtI%7*i zW(c_5N7E=xfz^l}(vU8A@%tpvPUBE?GIQ+C;y5%AveMZ&F;R{}>lBt4Mp-t|QpZjW zGmY#r+cUHsfRySuoy`}yJ1g=yvr{*nhQJPxo=()U;cHWL1?>N_0>J+7a?iO6GF+|8 zy^TcUPgQohv4+2l6x^=ubnlK&4KR8^pXb^`4)ILMs+YH?b1Jag;3ct64{-edc?8F= zUyS2jJ90jEfrb)%Z_``$3m#`HT)G2f0eF)B^j|VVACtMy^CZ8Y}W5=uyf&lssi8d z@;F+GU&``k(BJT@8%F?eiq2*wbo+dM{?`LyziKz_87)BR4&?k~`x2-ex1YKi`OmIB z;feUt?G|xRZi*>g=EXi;qr5B!f17larJNp9#>*c$dZK;Fir)W!HT7Q9z66{2WV;R6 zZ^8GoTS*R&weQ}iNF^01!9CuR8wcFsA=k8z>MgcO%M{b8EZR}!-K$!w*&;cjN|KE? z)y9xIdIg(yjoT+rShA|N29;NTd_s3Bq_zXNeMsO8QhG$wM596s=tlDuYZFa|cw2AO z2*1k`2enq?grqL8JwbCP1XXV~cjzYdil|T&yAQCw$*^4eb-+DihvPF|zx6g_lhHjDFHbpgdDm+8h`g__QTiqv*$qLh=>-#K8u`PW0pfNHaE8$er5 zI=on|)GJ>!2Dq3KY}5(v2X(r-0}vmF2^lys!0<$X)q+rFv|_<8T~>8mRoPK- zC=51)n~H}ertn`LF6}G>m&Stjo}vJbmmSx@#%j?l;q1r}4Oc5|-YU-PHWWa_s%hww zuF1OM=+daP##^F*|5hE-FdbR5JrC#8;@kwB<)Ep8Fj7p4-A~4>%zoTcmj^<@jSz_Oci5oESgs4Fql|n z4Cfv=64qYBie^r^Zy3NKJY4S?@H;Sq5#C@u*o|-=F;E%Vkw!R<03IyEiiWTp;UbYi z#qm#uTWZaDIMu?oHQmG87EV5f7mOK+ih=$l2@4bfK9{G+OaYDi?^U=x4nJbitiYS$ z`~n%-8DOF$i&JBsO@akV9Onb_kTDJCPVT1(0`Tk1-LVPqd=`zfDGE`T6+s+oGvCLP zH7BQzlFV`xYY10R0qhNMK911B_9x3cnW+=B44vS!z@Oz4FLc61jHJ;}vr+Cjb2~=U zFbyVCz{@}|PdoC#U@50rA_TEC8^?ZB#NosZP!Kq$lPF11lxEA&c9-)B;P%L!N0S)Ml9>tS!YK*c_1u~F2mbP>P$JYZn&?id+dl9mcj?_8w{M_;< zrh#lT94A+B|KHRA?jKZN78!)gdDvevqUI*AL3ygnbCE#ei!{ma-}LC&PZsEXwmrE5 z++LE?;9gDQ(F!?_r(!$;`oDN22NnSat-M_c=bN6;?VWe?PNzHQ2m?60w%xBUO!q~9ea`m=>)vKt2y1MC@#_x`o&7#ZdWU8!tY(!@VliEzrWlHoAYJSTNT~&biq6*rF(KhGW#uJ@B0kZsTb`Q%{9cZQR%drZz+~w z8a&%*k~FvbHrubTzy>Ppuha#q`np;fkcGvIyEI#EV}a=I?tYuw6K@Cna?Vr&b-xD#?fw@BbeHPWUBlL`<@DGbelNoe4S`h7G>-Zm0@jnhp1~r z4_*gZ+aY%-4c1#Dk2>yd^&1tAI%6d22nz?%jXJ}S(jiOmwH~K_JZRU65m6y37EQB9 zmFldy*XUK4Cc#s6n)`bUO|&W%{tsSHh^oLhk8y^x<9c$bfiiN-$bZ1@7}CU!@3%Gi3xR7bXHDwd@flBGDd z2BSH)Y^e$k(bpZ@z#1-&>c}>}YyrKnu!q6Hr6jQfKoKNhCD?rLijE*zf(U0v7EXZ% zQesG0M;R;6l-qz|U@aBf)C?F$DkFbjqLzHYkARp+-i2y0W(#=4mNbv5iD;yqv};nR|Lxw_}$6_$BR)MAUl_g>2y3dt~kc`8o)9BwDxI^@dT}S!YKYzBoEwu zzdJ6UXYH+$XLERuD<-;1{*+1*_GNE?>4 zl;fN@*@-L(kpU?_QXo4CGU28On2urCF%U&YVk3YNBrnNRUIGMu3t%Ha;J18+BwrwT zQpT*lce8u--a3KK!=8KXZnA3DoMYBnB>z8-ImY`p)x$0Eyx*-!3|0w|y#!-R^F+?(9~J^?KWr@~zx% z=WTh_&D&xJeqBo4ZNBT}y|yTdowmH#br+k(YP*v1-FCh0O4~Jzl#9|X?=Iw(xDz++ z?&efp?RvX>C9f`}Z7%kUF;S+akrAz(0eDt^_zUx z&U;<3Z?jv;;$pK~oOZ=dFW-vt2Cmw4B~gYatDcx&{`rsXm$Lo(#m|2Gx01;H_iP{i z_RoLj?r+*N#~(D=b=BAOBW?7;vlrTM&#|YrDfb@VSTwrnJS-0FH*|D!>F~*9%G2I^ zn*8+8?Mx$AA6<?d$mT*u|d5 z%d1~GJh*sv#{6cX7gx{jwJ%S5zs|nf3-fO;zI=N#`Kwoa-O%s-&Bc2LE;Xu& zr|nv$RC&XQE%pzYCHF6dl0eaIq0LoW{9&ogP%XR7^Y9^1Wl@=He&QL5?zPcBrsW33 zvJ6dq;-oU1t~1@kGlqYM4&R|Zs#OHUG)im@xs1behb%*tSgOIDQxwIQTcs0pR)vd% zH;At(75*clnG#=ZH~L4vTB_73x>B#QEGkv&Y*pdPh&jknrF#77!cw8<7tXL zEK45*R%B?dQhARU7aef_2F0K<-2Tc5++2p^>-6va{AZS_y1L_eo@029r%A4B%AF4G!XxB zqu7?=n6BHmpr2!zhN0;STyI*ALoRa_%XLN;T%ehnYg>+OT9#`mFqi@F88Cxu_XoNQ zHmaI!I@-{&br?ud9R&t-Z3hf>WEc}3!aSY@=Gi(q0oOZ@ZW|-XvMd?Q&|p;P0fxeo zba&v$mT8(c%nb{53`-u#ForXbWY=_D)pN-m89{g5gWk3dD~790xKXa@InKz@HE-m= z+m#JnHTXkDC#&#WSjEsbG`Im^pKA{+SeYU@4h#iN^BmPQ-~wH9$$hXK6^^>_cc8mY z--RJaC-nP2|5-eb18f?OpSa<9Y~e_?4QJ{FaXb&^V|Rjm$MEG0I|;TjACDtAgRzan zJea9I4&w20Ja%y4PNK+nogjg8<~W1#f|ZG<;cVti6D-Y*IQHCg(@VqHz~0!KB+4wB z;iZ#dPmfb~40r7(X>Nv!m*Lga!rm0yGjE2#lD-qf835mI4sF~IBlx$Zx^Xo2 zV>?W->!p^nRDJXZe{)Iw{C9riZT;te^c#Ot{i8ov{4NV`F#qlUeVB)T{IBQlfA$CY z`+xN}@<00d&&Cg%TKx3KFE-=uVfb>->*hXus*lrGT}E1bJwsglv>r|wUmw11`$i42 z{o|UC54>oSwf}JT%Jsk4o>)>e^dJBJZ~SZFum9~O^M^nG-M{rOzMK8SJ!JA~i4%lPSTdlw7e_;>vsU_%oevH2Uj$KjD!5 z6BSlG;*;SsUH75Qo;JD~?&~;mHO=kh`qOhSOmgq%<1-I$$9*m-bo0gXvDV%vr$KM; zSJ}^N@8v6dKRNcokdID%**C{CQ}3HOe`W70?6^gk2UdIyJ}#c^b@AwEfhFY4o%OBbwq6L#;|&m;0Y;sA_eqpGKeJwIUssDJ0P+ zHG^)Ixq59>?Fh@tG0Te8Uf1|g=TQ^U=$I*&sLpOg%{LrPSgOi%qVagR>;LsZuae`2ytDI2jziEKp=X*_-Z~=27I^y zSV@9F)wm`?^gpe2-f=AdPda6;6+}#nZ8JTCt-LP@4Vq@zcOiXFjUT0_uo9)x_VGv+B>Xp!Rw6QK-LrQ(=UJDl@<-NJx*T)i>=A%wd)O z9j5t~J7`rt_9};Tw?#36$a{l?p{STc#|Y)aw>(gZp_w3~E!zR5ZObDIP+cVFQA=nnqN%Y!6@*9pty8 z+5Mr>C){JgT=4pJU^v5*>>*(rL-#CC)yVrQnFW4$USD%{6I8zk@1L4GGC|K5qywTK zB(kkK1C@w=cR=7ollpzxu=}>5x+V-hR1I4zhH?9F7Onw8@J!$U&x4idfI@u>77Rm@ zPO$zFK#L4eT0wEDNGy9Hho0?>6GPzae5IBht5sU}FjKR<$e+7MDBh4XDf&=X4^Vpk4 z<}!3nzlm4N5F7qa5`Pjnc!ZPOGZLIRpG%EWq|8HF9s|27Z!YJjI~AM~idMQmknh`k7}Dv7bigIEkYGdo$pM@zgi$ zY!r^MGsn&fXMW(>c!5(8@X;(gkNsgBIZ1a1)iNjypLcpA?_=PXIaQ$@$qIKtLEoC4m2X{?V6 zZaBrdwTd%5N#ZzKU@}2Ga!kv|3V^q!51nNajLjhO0`rDR{*MMQ$-Mr0Ciz}1 z*n3oa_%ykBpuaHE6L1(leEKXTJx@ z<2^|7cVCYru^)ctyIzF4Vt3nJtpGE+ZQ?B<&XVmS-`qM&PPgqXK*P1KWGA)Z$+f3M zmWZRId*>+WT>DA#?q%oJPm(XTyTT)K+RYbYH{X&8<;%iNvJ%_t%Wh9z!GD+CD<{c% z2bgr_BoT9QCqM9!?DDpJx`xral6bmZ!+@P`>n}%X|JWY2$LL|~70H^W>B^l>zWttG zz9+Et2SRzEmEQ48U+Pn>CSNYo%6kr#t17irjc(ZBD+jzIe*6`-#nH?Mp?+i^Hpt(St;hDFHF88Ws_9LQws#dBt{!PRmu??2}tM7*BxL+=7bgMQR(9L?e zJYYHIU9a;@<)~Jvu@cv8l{l6z@inen?V-~q zOxrqQ*pg7^nr*&uj@~d;=A>Cas_-JJy!kbt4X#mQX{N!k`H8^)ZwNJ6TA+Wg!n6JS zR|Nr}iEbdKRBH?brg?mJ#2^(Nv$YCf6?c4Kh#zFaJY1D6f091-*>^$}QKuEAuN+m} z8CT{7k>SoOjV|11wqDWy*1`KvG*>TGQJW9xF4L(-^;U~z>j+T7(M^>w0%%zYWH|ZC z9$q+(W!biDgSOR)%fJ~8fhn$DWT1LwhlpxNm563`H6q6Qo&)0DAYauxHUSIJ;BC!xiiJs)SYuHH&i_Jvp9^ia~$F@c4ku#_+z|=1x>PC%@gO`NZpl> z<0V$VIrl@5e#`m9|0bBO!YK7%8tl7MfD12hJV1?w9|ZV3a3kM|mRUTHqj_NX7e6U% z@bMB5CG*C~;F=}Qv-8TUr~+_^h~xnANEH2A$eXz-6;jRw9OJKy4NgV+^%|^%dNcYoaUFiTZcvWQq0?()3(&xU3R3?jtnAx zz1y5FHrvjw@K{;8DeE$m=_kG&U{g!VZ@7p-_NEPRMj{Si4 z@O%Fosr;(lS^L{x*rYEP4{f>E@?Xphue9Ud?<-phfFN(>Rh}xB*d|RgCAx&fxs535 znCF=CuhM+C{f;@|1XPx3hpq~zsQNShfbH@WDlwl>>!2bXH7Qi3DPEw4Tm>~6^*7W< zmNkzN+u%^8++q;o-c)O!I$WJ?eQeT4Jj_^a*U|9(sMT(i>WHSwY?(bg&`^z|Ds+kA zYp5~gLCI4*CDcpZD&o0@TotGq#e?!@c$VQ9wuU}ZwZjq!@pmFkaeAeM=nBhK;0g1t zBplOpt5H5Km)>`eOVx@%wK)zo={8?x_)@u6r>iBAYEiV33d0KT7%)~qjaH@Jtk4wz6I5XZ=D1lx2p0ODW7W4M~^TDB{JJeNU%+W;$$Yp5<6 zmvD{>ltSDOu4xns+yp^ys*dJ4R$(WId6%epuWxF)sgsRPI`OK&PX!(W&Wt=y)?gSg zA27otUID95+yLHSpu5HZc*9i{u+UM7r@)g;;FJLw-O)8L0bl`$3aAOj=(}n$CZGh| zCsQ$1**VPgY35gj3Jx89GDy?9jK13k~?G?@QZ92(+u13Mz#uFEEpH& za0ym;AgzytU;*YZg&vek@k+NL4c@T!-RD!DPq*P#nSdcUS;ndFMv>$AQw(=Dn>cpl5ZG|D zY3z~Nd|-@m^clcq>0u?Bq#8~~5dc~^ofsJV_VUcf&e($ymtiuEf@BiHUA`fVpR|E6 z{^!=~2qU>u;Mv`=XTh!;=SP>s zFME4TANN)E=&>e#+@9kQW#3ii?f3l3HGLR`*WsRPM1E#WPyi$4s_S0=!~^(vh7(?j zD;d6Y_EiBXFW}GXx#j5~neEecz*Ba-DtPZm)DQ-M^1qPQ1;=- z#dY6{XK3Ziqt4&Q)+gNdcJzPFN++xxIJ7j33Q4Jk32MB_c$LpH|GfHPh^#Za)RgKWqG>{J)vxl|TBE|DO8i4Hj{4d79^hQj-M=qNR5y zb((1)RDaWBY6lIv$}>IsqQvAUbesBADwW>x)h=7Tmxj%aI z@lBKNw0MsHw5E|zs?*26#g-@@QQl#RrW$p`_|@*)Mup<|lPYB)wp!_y%9Ow|CuQE` z4q4RficG85VJ#1p%5}IUWu6no0WWsyY`KeC{7FMNZCc}W3mat#uT z0=;!Izh`TTN*p)vF6qd2-?0V+XGXFO+(i(g@O}_HkW{PK80C?zQwDKZ0GM34LmaY) zX<&OrfQ4rfFN)#W1b!S4|1Q|6xrS-=M})&XV|cai3ZMtjg#=;{mk~ibu)$OdpmSsk zZs15K_Dc>4G`V^&waA?+LN|yllI@O6TedY*muwAy(9sG9$i$8lAQ6AGjDQh9tIv}t zOto={^NBZIq>*Z2FI`RIF%JBB;D<^)nR!9t<1kIqXr3hbXzVWMX|@W6*u=4KJK20} zVtL}mX-on^K=%)f#mv6Ii^0^v&IseFWG0?Vd@Ug$gN1Q`0XVX;A0<{gz@A6ACtJ?r z33grVl0b?iohu%Oo9PY`UyVMySfA(`&dhAQlrdHvU=Rn}z8}VcA4MVdv6f(e>=P%< z0mnzOVYUxs`5viPYPkZZ6wWXO(x?g|noy=^n)bEu za?QOBiT=8@ej>5un<4I+{)`xZNq z(<)tMm=7#d;j)h&07U%+F)TxIAjj!9pQ=o`h6IkPiHJI6*dv~5w#pn5SemV~r~+r+ zfQYE0YO_JLs&BzeibZvbs=$a0YN0a6(bcy=2uz-W1~TrD;&k3g9_V1r3zJfAF+rA zE@L`nwv4&}FKvdU>P(xjmg^SW7+3^CRa6yth84=6YSkLsp}A(6FHsc$4aC#UHqahh zM-*{_m(a08;BT}4$$(0E@Pz-O;(6DLaF0hk~hpeh4NEg~O0&(=vShpn2j?iz*v z1vI)2Xp z8_rO7B+F4vS2ISIrH|}l5(g;71uW8K6R<f>E3i=?3GtB)+9^*SOZe=)<6TpG-U?-whEeQ9RewWwJSq zI8R_uMJaqAlNFBBNfc!`SX#FK8OKhBFLHN=U3(NbS@hX=W9yr92ZuA9CkaUV$<)o` zz{9gJc1f^24y@JeEO7$G4?tok**Hv=VSFCh*))uNqNSsmJN6SR#$$!({X|RQsDh12 zHY3}Urfzh$n5^u%gCi%1$H@|pahe)uFyJILXNK&gQ`Zmdzz>3O5`5Mo%TEA$BItI8 zgB*JkOUG)Un#)-_^Z`kxun=tPmOs}$7+((IpM&S?;Rr{Hg)PrdG|dcwjIvP0IK;XI zL;)P-nCEVYz34M2H#|*eRszrh^pwk%k(yp=8S@MnNlDY?Y>K@V*@Grerb+CE9!?@} zfmeB=1s3*GZ>-OP%uzIK+t`Z}599N3?oMs{%w5C@PMyibFvn+dn$FDRh93U+L!gJV z&P(*LKP363b{$CZJ-0MDxg&B#kGe@PFiH~EmU2jR;#U;#eD(<9CuPsYGsRuvgUY=iGUKXAX zxKP}*w~Os(n z#f@H8?<92b;Mw$5w_^D*Fzi$A&qR|y*9;i+`iid+h4PdGo*M8f2zWVB*PcL@eYmif zN*=_wXphgSk9*#Y`xG_4JotSV2mP$FzIgKBndilL-!Jsy0?fFdS?Z;(FQ>D5-5{^% z^z44EuOGYfa_j-QiwBoH%A-|42>BSGPAIn4=BUy^i{VP25L<7vX!)CTtwHlG?pq4I zK|(+uoKjr*5S18U3dD9PRCb1s6H=MBc1yyt(GX~nrK{m$#WLkendX2h_!1-34}gQpb)n7i zs4OrQ#4t6~sZz}fYL*&pva_j%SeNQ>hcwp^O6c$WeX5KYoe`N@vqDi+qxtRxReG%w zPxFk_%z$oK?ubHPX{8om5qkdtpre6m4B`>WJDoDmGi3mj5<+i@!-zo*j-{y{YB2^a zynWYZ(C7`tl*>$$EuT`TUTTVEUaSBKk;cO1b+*NJ0h6eM7FVii4AtQ~6r$)up-CgA z#Fx%$zfK){h(Zikp+yEE>EC5(0g$T1R7pZBV@O`lBu^8(y(lv1>k%k&d0;!E{?OJ< zzzStxni{YJ2_Pqt6Y$a{37A~da;2-taq>qSIb?g31vt?sIhxcWom1g^@HFC|0D%rj zK_V`Q%V6M;IXxJ{vIj-bgk{+y)h@O>5hfvV6`Daded&@Vkyr^w13UpZGKtdD{<_jHBC(5D50cJG17PR_gaCVJB$D0GR8^4_RUQmfMJayDBY3VU17)NP z72ULSO;=@5C#Ghp7W^`ZEUU=m)i(`bEFDf+z*H9414l_u-8LmyyD>D(k!2L8jiEU(6lp}fOqNW* zB}zh2|8f*1lMqLss>3KVu$JL00JfM~)_6R}c$}^9#KY+#%0f>G+&IWU)`mbLW`g}m zlm-6=a_z+0C;$j?D>Iup-;zw18@-Aj+unhnD|CK(8tqw zmf>X{kEatqb!YQ9$fv1z?F zP2>68*Mn3W!x9%*8ADG4yRZT~Sk2dXy!ZwuX&lV(WD(9U@Oc(~#wkn@M6d=obwhLP z=Vz067AE$59z_1~A{i&ZZ^6ZK9s{ps;VKI9xgAfihdtmMJ;wGR%5mr{7G5~PR+I(S z0JtolhVVC?C2o-5IG>oZKaH%pkMkh1V{NTtQ2W!!#nE^%!=HzaA9<=01QUFQGeUfR z1ix;O=D$7$r1^gjUv!8(-Nqze|GuJ%7t!Uux5K%8ROtMteiiTW6;Fov9xWNi&R09d z1$;X0YT5?EGKVr?7MRYS;UiH zM?y$?#Q)H}Y_G)in)pR7x2uhquP+yO>8=)ez60WruJc{>I`Ck9 zMQ*(!y~R$>+jjvZH>s}VMf=7lQlz@NyzKNy_y}={h?`zly4>{EyY;Sj*<0;olIe;B zk4T$d`|`9$Tq5fqT_V3UZ7;dp$>gVk{~0Y0pXaXpx{SQ9ZTkfO=$=uJ!RK`zlKW`! z1AHpa_(mSsaufM}o88yFviZ5aX!i}d*>Ch<*T3$@_x*Ks27=|O0`~MKi0}8{Gm`Ol~}gSG97dX zx|@Fw*dR0;HU5-l1-3$0(E(GX4$7#*oPbOwJGROkebPh>UE$w$D3)UpP4@s(T0@RP z0!6b8gXPHXttKZhbc3xjzz7wN?3rrP9hRf2M^w91qZ-s+WtwSo2PbS3$mtCQie42<4Z2EG+y}CiOBCP17>MlaV!G^z zrAqZWhstGC=F8CeJ$g?eo^ydD%4Lz^g=$ma2vkrk;zf?ZgAy}^V7WEe#uiKBo|B-^kRsjvhLBkR=qmaRGVph&beF!X^<@W|0! zO?M5a$gr!ANEnM_siv(-GKl{^fe&S%4NOA^esbV~fvpe`VfJOauaWdqIti>N?vf&E z+%fu=>lJY!Bo;)`4MGglu^*oKs)KFp2FAB(HiP8ODPVdHUN#X%5F<4G3Gy=98M zB=DA@cIIQ1q{f;|{RvQ!MFQy!Z0lj<##u7Po@Ip5bfOYUvCMfeolG)}<7|PGBw7Ib z;K+$rahMo>h9`IsM43YJ_UgJDd5L3s@wpccU=(L+_%NCiMuwRzBDgi~Ef0J?0Ur35 z$G?yiQ+sv0dBqcV=k|#1E7_jifAY0<7oh&N9aUHUmY3ox?l*tDKP%PU?y4*M?qvOg zcogH2yx$iQ@)!V$=lfQ1y~ZbM|DWw~ZTyqhtNp;WzY7yLA+C+}uG_f_<0wjRkSLD! zs++HgZ$sK_yLr34?Y8sXs=Fx)Z*+>-jmynuwOzsC&1#o#)~jtVC$5dWyV&O4%bRpk z8>u6&yCiz!w0l){BPW3)mz&F6Dxx=tOJgTXB!EM{?8>Xt)pl{ZU6bhX%~c3T-rc|j zmmOK&p7ypy1V`Rp7k-WW%CGTb2*)pTd&ZY>UwPk?xuct7x_M6te>K2Cds%$Hx?;!8 zC{G5vIq)Kpylxupp=ei!@>jCrs{0rB_}IvOY~GbU!)uxtJ;I7>D{dyg@4SC;qX1*W;zmf!A=oxe%g_4pn= z3TiJ1g1pDGDJ#$n2Vxt9f2Ewir5UP3@;8$_Grl%usBD zV;CCbd81zAN9c&AP)xBJ41~&Dso$g!eL{VpOFa9LMgqfA3@X)_a*0DMg&JHFj<5s` z=woz3@eR5{3nnUwJX?QP6!@r=5xb(PDk=$`I@6-r{!i;PB{Uh%VT8te>agCwM0Be} zbxIYn#M14fmWZe(%^ zHBGk8iuE$5kxgVr9LES{w#y<4%x$E&k{+hWLu7A z*~XP4p{UgXKkU(vP>1Tk2=2ftA{R)iDzX*Iajd@UjT{^FEdYfDlmXBp%g)Gx-z4EH zkV#Ps1LQXGh>)CBeHWy@soIW5652Z6Rq9*NVpkhykc}1BCw2u`JJ&iEWmC6)WKs+rw;0H~W2(LCVmTAsi=>7_K=mj6QLG z^Z_m0k*&!#*+12XvxDL)gKX2XfLAPwz|qjtNW$A9*%k@vAT&mjV8QxEaDi=*Ke9n; zlbE{d6!~nezV5gKv*0G+q7je}0GR4YWXU8Wn5mC|V=O`(RvN}r9AG?fvokNpIC5v$ z^X8;9MYf8TE*>XltWPIdoMv_uJ5$Rv{M0g2vR6p6{Ro&L3^5L(g`3R1sTo<5VU~>n z2Jp)ICbY3{k5k{12U9!FaU3N+o}7U+$H_XFx^f)lxi|MnB*YmG$59ld<1otg#h5_Q zI9S<@YIJ=?v>BPz!u;W@>0fY8<{;FLy_Ayc$I_TnQ3ogAnt4auhi7AhffX?--$lHBa`dn7>!L4qtTX5Z-X>Mz>D^}4M1_<8&RaQ>UM}fVs-0~SWBlp5~Q){kQj}^Bhl-g z5|4ybxFjAWw31G55?Wp5vm$eT`pZ$>Kek70ABOBv)!OLZ3EADR>2GB8lk4{idD2^v z^#|SM@0X2AbM+sTz3O(xhdF5P)--%%@?MDAa|_hH*@B;sagm=naSI)L)cKeDeu3x0 zx^Ip>QR#cX(fLG>vZiS!&j>1@%d2;@P%t~r^oCu z$a7DhV=hhE@?qLB8YfldtDpi^N}#`nu+kF93AUCTXn{5=5amiVDD?gI0HSPT{Dtdi;$ME={3 zV(0`FRNc}o<*L4*LgJ@Qi+CeU$1>EBu3VL?ATAaejCXW{1c=zGX3Ibpg{#7mHCgW) zS1D&*RaHryz#)qU#HR82Bu&QQ`3eXnbaIo#bHwut z*;u%w97jA|j+4-paDo@f+5*GEAjSp=dJp^h)W@r_pSVVnuA+(QE-xZ~ewKfB6C8su z$74InoY2E#SkKvP>Rq^b27H43z=?k{c0uU7sp08(0AWC$zqts#C0HA&_1*WBnLiY#A=tW=~(;l%_;nKB-qVP~9%@K3~_>q!_}x7GUo*LMI5)3>j7TNvXX630NU zy3Kc+sC%~V+#-qn)lz_C{nfGG&u_4Lehp9I=ry4!4`M3h2d92Wr24&!)2kt#ph2() z4gUVC(IE1j@H>EWr*K}ZdJ9p!T&#%iVz*jfr=Sw0d@Ehm!XS0S+uQsy-)-|<=Uy$0 z_GZ0W+^ZShX|K29_H?_rPCK=|N;@TObCPtbn|IfR-{L0e6e)ut^`xs<3^=}8uL`Hd zUEV3NyV;V&Q>R5Kj73M>=I!0-b>6A%iVWHjcRzY9etFt{KZSZfB!PT`{(4u!i|y6J z-0P^_81b+v4~`6Rb_V?Jr7_Qbx|v?s+d?mc}jsQaF0;(>Tw z-d3ag3%6GflRtj=L`yFpjP9nqht1Lh+V-l1}rXF6<2M9Vh({iYY?IXfB zs-p%~5e~ams!9Wmyra;Y=KC5|uC@^XRi|`JH-8&3Y!~nYiQGS8E9ElW`rkmX#;p3` z=%+NzB9$cxqfEusK(T5hW0Nx+O147+x+Pm5*`z{*W@?6QtLDHkHITxZWm$UPwhSWV zNo8xYd5F}?F7hj>fD|M=nnZ3}jy#Yh*|1F#mpxQ0OO>@jA3lv?z!C9uSVcEmGlq_1 z0(Pio5wGpowqe2_fE5y?ZCZ|EJC+P4=!!u?q@e@YI?@!2L>Jg_wXIvGX$^Hn9VmvS z8>R*F-;!)wu?LPyLbOeNC|RcJm~al3p_>EQf@@UCaBP`K1P6|}nq!hW-mn%a@nfRKctk@vV_wRTZ*(Ctf#qgq3NC|wzm)Vm7VVkPO8CYd8!84jJ1D}ny#tE6@Y z2|^*5Rm7^3N*}ULOmrl*D6|I*bXD&=IM1+e*r}t=EHhT|L`&9Th8=forty51#F>-K z@dVqR?k74n&(#Eb$ymu|XK}a;0-TzGIR%|<1-Tcx<2a7}Bz5xX4C4jHap+AJiwtX? zBZqNT0Tcchd+yTC z!pSNMF=)5(1c$%_*qeIGxibx?*bYrE^j9R!RguB&hIf-!C$+y+Kd)?D@cOmW8n{KbOCJu#lZ?m|n=Y8c;xV+o}v0TDTD>CP9`(vcT zFH?KO4%%yUF_GoN`$hEbso|$z!z<?5_m=s15IJ2P#h9JRRLx_b`~eICnkJ*A{Ry z-ROxeugOdGsHy6+T(Z~kabxAwbHM$tU=cs6dIJP z9EXsA=-NBB#Mj=9P_u*p7T!}0810CnWtuI~)B%sGT~Nr!i0Rct#MHUBsKfFd-~a}+ z{xQWdEY11Inir0(>N5m^(rc{ zZNygSa-HRBb*@1qO^YqDBFDBG0)=XD)tfS^ltwJ0d|N{;3PuN*5_qOLOfWpY#=ySWB~I7vM>< z$u_Iu$kiR5aR@RAy6|v0Fanucp9%P6Hk&0&5!Jm)SFI& z*?5*EUJ|(DAj?4f>XR^;`O%pjWXb1jvhaa2l0^F!htt?erg$(8!U$wNo+pFV7({aD zgJg;^D1R@`?I4Y!F>uE@&T(MobKgiK&C#aV%dqZGVmEfvQD`W-dxl|tklIrMj+TdI zSGA06ASvf z`jI;weYOTzRwuD#PjMcn5wOrC&1WMmoq~R~Vp~mPKMLmBWUMQR9R} z=i5pcMzARC;l<~`OE9*L@tJ3)VKz=Z99V`EE%Gq6wKxLq-Pe2j>UwDHFUmfM;q_yeIppTB+Z(qwl`-CI@hdmteU%i?mVmEQWizC}ZVo{2_w-7H+ zSK@;j80}Sev1?zh#I~Fh4+O~#bsIm?7P}%z4%H>Op$ZqoZnaqvA4E?43R`hq6yyex zUj$GT#V=OtmDp+bwxl3;2maf^VAmzNbD)vlrhUKuMd60XckNZ@&JQ6jHkaE|sdw2U z@e>_+Bkj6CHSO)X)9H!%kKq%)#Ozxevt&+R=bLNmVH%I*C5p7)LV z^2qbC%pZ6)Uh5Uv*Y71-xuUFn1q#2%v=7%;?Cg3rgVt3mz=OQiv#3`-0O`-rRGFDG zbeU_jN7OeP_Jl82YCY~0DfOJL4|!VP!Ve`;ppMEs&kMB*jrdXZ2o(CS1ADNY8r?=b zU*bf%Wt6LIv(YGZ54aCxHxkt;m8nt_(OjJpTS66-{;yWK5-I~_0IQT(wnDxA?^v!S z3grs@7Ex8XRicqfBB2@fcNw-`;fu0&z%xq@Rp~~JM+Y^Y;RN9$>Xd1eutf7WI*s}f zLLzg3-j@(pX6mTUQ!xCvR;~&>U%N{2blmFle3LEH{R#pc`ash>&-^XVeRj;DH#PifC$u27Me@~Rs}9liLs0nxTeb%h zspajF`gDB|`xzGPWG22y92SbxpGjvnb^U zNTu4gW~=&DISz7bfSar$3PUIU2-}f0QuISr3in7+D#Wk`B+sv1#JiJXA-XlvNSa;K zAl@Q-q?<#_CVhzqMpsP>a78J0LSZAH2dRZYP^US@4v7!&vEkx8u>(9C4~A(PES!}b z;)$`uS>oXN%Jhe^=io_3b{Y+Bkm7yNt)W}*?1Y~X|@1N zOU8Jej3Xlpv&k&Nlf`*Foh-k}gGDyUvow#+tqYt4-&kkMbP)jlxJs0!E_Uq+u!IKK zp*sH9Kc9?owD!$e6xc~H%JApFAi9q1zw!Yc@N}X9ZsBDJ{D}=Sv=ST|=YS*$sW><{ zW*ARqv-F#MH8GqZ%@FLdCbz%d+u62_Jn z&SOUpvF{r}JdPrd)aP@iTHo+|Eer#9heRU*LhPCoEBncH?YF zpVA09f8{6np8WFzQ$by|s|{IK#@=q@A_hDzA$Wy7MMOusr@-JnTG|IR*$W}-kN1Q< z=9fLU`w6i8)*fK_&tDHLk)M2*IDvhW+^MsZc9+}kr3iq~A^VZG^6u98A@x?*g)hX- zRf?z6cJH((dr|m4@~f&BJL3H4ZLcCKa=EuH5eE&Xdj~J-6HmnG_WakYQ9R_dA6kk0ei6WZH1lA=_nbThmpm)C zAGa_2;=jMrzUp%LiZp+1d$b!We=_sMO{eGi=c!Gv?Ejoe%X^P++Lt|#iVn9=3mPHs z<9v^K)9fIMuhJ|B()h#%4nRowR4t2#6~v>Xw>6fi>&m+lBlB+#OK(~c^G>KUe3@^R zn3_~BBeq#?G-$pqFcei9wUH5`5n#xPa8O8do)I+mkBiJoVx6s&TGByDXx0biH%Dn5 z6n~>#7Ag%^;E11sQ>zTc0^gwSakC?|YV{__h-Tw0UoKM>hSbiZP=$wynuqmLh3D!m zE`0~0zt;S~>xgc%bcL(12PGQ1!ZVTOtGvk46gy}F{ZL}9j}AFlIBGL&nLltC4*nw^ z3xT2$E3|l?MRks)c#dh;#L5xJ9I)jP`am&tnmV9sRjR_5>IXDaFSP`^{=QlxX{#vW zG^&*77KhqA1N3y1!d-hKNL;yAs<72J9FpD~P%E9SbI0RKldDkzQ-!~PUpu9l%5mMQ zlsT?_#*n%gAi_=EAT{SmhFOwM$#8~*5=Ouq{h>tmJGnAw>cOC2(8JIj8l?2LVd?-b zr09gHl1g#JQD74x?m4z$lE4Zg{T+KqVx2AhDjS4T1apvJ5ARCEn#48`Sc5!LNDeAeNrUXwBCZi)h)#IRFbtiP4Iy#r zN>Qi0DB9V&Cp!nJ6I}!mZmvHE-P}r2p|X9 z>zMr_v;>S)iV*J4^W?%`O(Go3y*%@mxs3y?;wZvN2nT0lQlk(16B2mkGBNm8h(8!Ts$hXX^7LN|93*UG)| zDoW1{D^1cdK0n8P03%Pl*fi6z4in{Rn#EJBC^3#fs81#uOdK_Xf1_}j4y#VxJd8p+##!tGUjfLhJU@ZoQ}@gxcV!WH%h-w+pM%(& z`pdZ!deLm5<1^pGX^>!P7A|3BBPBbRk{R&b0?$FS;v75f=XkNePUMbp7{^mh|2&JP zH@xvL`oJ5;=?~plrQOrdp1m*T`sK^Xk4Idwr%3qC!Dr(do)37??=ir0fb^IQzUG&B zReNobknBlh%HA7ruRWoR-`GPL|M1n6kvK{GT@oY_61(g5qNtZa;-K?I=W@MW)1D^f9ogl6nEi>spG&~baZE&L+A!Y|Sz ziKRN*{JJQ3_c}a7%2(T5yd>TYc~z9)SQLdaSVx$=oDHsWHlTP#SS43U%s zC;6nhk|_UJ68x94JwlA3daZG9c2E)L#AD8QUS{u0o%D-pxBH^*9~|!Kqw3FP#(gP9 zWB6q3|F6CC*o|e&((?`<=?yb!kGW(+!6UM!}2VdDmF_5 z1)l!c`ITUwSnM;)RCq=b^;Y!{49_$B`%J4M$gDuBJobrYq#cPcHK8YS5aA1G3jqhU z*d9|m5`~?bOk`3MI7#Abot{{hcUj%@3tp-ThcXfBG6erjoirPtP~O3a&7TN!NH}JX zi1jvCuL^QA+~p;*Tj_mp79zWUz}Hr2z$dXR&;6zX0P;~hk~kKa1rF-%wMbpq+n0z0 zVZXq)+Z@9(HND%#lVjl(R}r1xaPsfq+kT(yuoY%pXPWX3e^ezLI&c%heI9(Sa1tjF zMr#VBPS^vf(eF#U7rhJsr{AjaT$2Eq@HOUy(<;@zz*glt!*JaW%NQI}BkU2g!?DbG zj}=6=+WjqXNRM!WP$m66(&(L3#TvrJSheio*l|tGbyeR~J;yc%YH7Uf8XESQb=

  • Pov=@_=-V4Et(Q(!81%hoj?b0?T&a7@GTEe+-v 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 VsOoOm9I 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

    $|i5?FuQ4J+*>6E!FSTK`D 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

    aT>3PLvjkP2C@tNp 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%0A??pjFu#!-Jv!*Fc%JegJ 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%0Dl-bO2r>))Sw^@rU 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ⅅg0C~iIYXMQ9(slQ7$is_#WFM(btXL-F-SxA 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

    8@wUi|J~)AgJ6wv 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 WhQCH8gg;0<7pIlus*9)J_juQ!O*4fd5x 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ⅅE z$8V(W%LZVyW`n6U->58Uc_@p5c`)I6hirXJ)EAVaMsuJjD$4;*V^7*mQ!o^v_m*#n z(m_oX6^Uh!+Csf`(Be9R!1uV$L0i_qu|)GQae(cxHP~({diSXA3gVDyi=HrROW?K0 z2nyHgG{HYsq?%mk>#TUhQDE(`yB35xFAz0_j>o^tgWFzDm6wVq^km)Kt(*)66)guR)V=|;Oq~smSeA1oJ3M(jx;w4KujJ7*+@6c5cW4}+?hhRr zZ5MhM4{=q77T3i z3~st(RAs5AL?2=tlzm`6BR##7>^)P~_AT)3Hs-BrFg&BH95#x#-%O%V>mG$)IH zyg+VwhNs9~WLfTb1;t^oALgV1&eAZ*(iF|y5IbRo;LV&kpXNA-gLoRw+}Q%hj!To( zEF;H_0}Lloo~^JdN`C(jZ@{IZQGZfVyQCJI;LCBgEXOtKf#wd=%G{U)u$=pv3^5wrK8eTlh zb3C5~c$#4{vlvZhaGE2WXA3xwC_)op2hC%Df^D3H!77`iu5m$(^i7QI7?1N}k;HIu zhL<> zfJH#hBj*~-m{!W5xreR;tMm%-v555PJiS)*BWe^~S?1H%EX=NCxD!-)<6~gfjXB{> zopr4c)ycnh$N0w6Y4z$8x$pzj6V0y8p9kX`nNFpRL&uzXv*3oUWLwvhXxz!y9MP5X z+y9-clv%P;{?$MGqtovXKCX)O>y`5MnY0+PQjWv?Hwa}2l$ZLhEO({4-VZiCl`MS+ z23fH7wEm#b2ij({-|Ibn-&gv5ZM|J@wE^9#O6?cLrM}k4B3Rq+`i3@Gll5IM|{y^WB{cZoUq(NDi<$BxStb5ynESSp; zUCQ?R>&vx57Q2e3?6&)@Zfv#wzSrNbdwbpJYy17S-1c>{&M(T%dbcMlVKVrozTX>U zWp3;@`~LQFv)`%8c1w5Lq6wup8`anp{bILM)|Wk^99cQ<_I+)z-E4{76c!*>DZ9Sj z+YEZdqAfLD)0A~d*6O|8VAH3I^PO6(`@5Z?Qy28qpSI8Xsr(I>C*j49OVP=XSigT3 z9WWnjH@Q{$MJx5^XP~+MG#n492G(;%8Q<0A{#eGR2LF^FCO?3mGrlL)ynptdGPlP6 zV(8;T-$x95(&i^D`aD{67ry?uST249qVQR~;?evz#jVa?gdKcV(~k|VNg~As9i?~< zf91PJX+j^5Kc(rX6f3^a$m>4e-1hE+oZ3(Cul57Sdc5b8!k(mBeXdkk34J80iR}h^ zz;f&m{;Vbmoi@{F>&IOlv_bn#060bvoBUg@b=2q&dV~w4%Gh>rYkT4C-b%XP*nieC>nM4fYWJ*Uvh7`SCXiT64&5(m2XHjptC%v z9f1SwXGg52cA2sPjvD;YiO%+E8fKPl$_6LXt;J-S>%C?~rOUKgmOYS}Gj7vm1dTk* zDWJ_y6-HruddaA*#z{>O+Pru^Q2qt0*A%%?7q|nF`@^pVa!dFh`VDUV4|@Ec%*RI@ z&%NxhEMP?Sh!H@ub^I&wg~=c2;NY!TFMsu)auN{ucI)6+sr@sq#<%Md|Bf58b)V;~ z23xC%3fB;r@=SP_*LX>5bhKkeQoEukkuhHaHLH)0+7erwb->AiAOhw<5uKWN{IXte z$Uv6T2C0>$x*#=A+O>lY*X$iKovu_9Sf1LzMWbGwVVFNv7`ek*ipX^oMm#)j^lAXG z64M#AM4|JB5gdsTI||!;!L!nFy;iftWbzBo_OuN^SnqBraGvK)vf0Bu^ z+!i?jFwzO%6%NiVp)-&=f+Pv-*q3vi__oenFmJNtajA$9oLW~zW!Q# zdm`~Ix?LEJ#DXEEWY8Eaui7ojho(n^r|6zhfrl)b{h0=c`5sM;><1R|kTbMsW*IlLUhA0%4VUMkqN_!4nlJ+LmH}N zm^MvS?9(l*C}c!B(9Fvd7x@9CYv(H7h+;LQjb0I3kZ)Bvh8$lvA%sI6LNugk5E;eM zsX-R|p-ywT946d*W(mQK%Eo~wH{-PwzX(kIaL zp-)j2NYgTVrUU8CeTZy&+q;UhBAwkT;Se=_Vu#d!J~aG*hE6%b&?PtWYOl3nh5pcO zzXFpc`I%T17=&~*bSisBRmL876nI0MCfar&v|*LZDKyZKLS7D~S=ppV=%AsG9Ga`i z4gBE{(R|dyt6TqY2&)~_LdsthyCwdKoA>Ht-B2KM*Qp~5Zbx!C)8Z1}gN%M3OoO(EPk}2|RH=bG}=;q03oF@*nU2}%>be_Z`Kc1(v zDNa$kK(T}K5Qo+*p)pBkvmlLNifKSaLTrmNZ|P4*7{z|%Svbw2DVpVYmiahXS&5z! zOQIRH=3eIb5To34{V1HBLVSwSB*4hY&?%lz1BjQiMix*_*3=&ln6UP{5{=%Y!CNrBs2hn8O*mtJ|qBzkC`wl**xtb!2hKmLGbm7G0 zWNgJgjshQ@E?h)(IXBLx#Av*L9$xsT5jN;PXvm8_3}IUF0Z17%%Y@6-%5_7|%+=G0Gzk$KDJFSOZl3A{AELAd@o|NU>jeaU_b;z}v3lUBe&2`QrBRQLxv1KVrR3t^%07hT_?QuDk-$y8_z>B zaCSv1s^SXLI%08f2Q;!ZrTo=)JCL3UsoBAG4kMpv zlh9B!gA8&f8qOz%dpAP{AHEmCm7bFu*L*0|L2{)L5$IME_DI?#|Eg^kT-!tyNk4#Y z+%@R-i(8=E=o)nU_n!~C(HjKammY%6X0I7Lz1P3gO1d+druWNUQLfefWx3NzeXnV{ zt|)~<0jJGcEjMdrZy4+SUf*AC*E^*s_C?t@)ZT8VYWu!s6#a73Uk^5ygTh#^cl~0& z=__$SSRBE9S`m42T*OjMkgb#F~MO!`*WHU+663h6~fc)8s62KwG8^vz~% zY*c-x>b=cQ-S+5~^q0D_(~WDg%X&xU6C)@KX0Po@^Iuxhz8O445|*2GLj(Nuk~ zR(9)tq3kHv<#JzAs>@nmYddwYR<+%3r)-GT>Ta{yt~bSY(4$0`QXA}h1<_|ivng## z?WdGRKb611@+B#soI{C31iQPavKU~b`dw#Ign3%W6d{mLo$~PW6d>WlI zp49JYSnj#bcph~6+=>1u?WrDj_4;&XrO&3){-KPSTR6)_@xzHXAEo?QZJxK${8iJ7 zN3w6Ht& zzkSPgS%!OE0|Fy6qdNOq6bqJZ)%vXl$G)DhDyt@3O=j3eLuTaHfN2bS9icsB_*Cg~ z4AZU2jRwQlIYBuTS&@|(@PcjB#VObBG-&o}rY#&YFWarR;D`fn#Miw}r`nQDU;!s_ z>=7rbjW#E~svU4GnF``%&{4=Zbq2J^BU-c8V1>5a=6Z+X3CEo=bgwbM3o=a!t^x*# zA}=0@%n3_DK~AK*o7J1`Hp4cF1ybV;ka)2z9CUcO!wO6f@ZvGY2viK;2AaqbL8I2m zo2H_*zI(wiwKu%Pwk4ezo-_oYGBtD9?Vhxbj+j@(niEOx*e`5w{89kJ4krMOmH2~0 z>osWAG;z{v^Q}hjfO%OHkJkfDwu<*s?PbT1DMji;1f0OpxIcwwIf*}JS-$p)uQNQy z)Wjw+N|d<<(*Z-KBlOxF-)tWSf5wtkaBZG;8K-|xFd6|97 z)mSo7Tw5G<4iDO*e9U*xYOlDi(61?MgBL~igs9MH)yb1^TRA$G$WoDSA^?sAnN{Sb zEQnl#J`}$=0f#)#Gri^!+oLI?bdIYxIZ3S7H9_qdQbVJ;tQa5wvDNL`JTD;$hz$Fh zZHR3}6$S2<2*hqv6NP4-1!8(2@vOiL!b!vDPbj^e242A-S&RDg!bo}THVqA%z>tQt zg`rDn?`|0C5IH{Ga|~I5uTx0M3*2h+v(T!Z(0$jmL)+5f(4*VN(~Ln53MQTp$H8a_ zDf|`$SP}bP2_)ByP`6115G`z}&M7M|w^oncm4M_zB`bbaT9=kRLT87>Ph0qH; z-=wL(b=UWO=#6Pq9dwOq@3bmklCPsN@=WCEj_(K1x9G0+x@lWvRRL+V8=}A=X+0$E z!zzpqh5nGToP5_Hrn)q@xIuTSyWY@@0&XM9RYEigw`Wo67DPJD{p3x?G9+)ouhL}bbE*R?7hI2$7h1TLInL&i}WJ=ch ziH9AVyk${}7hV?6$PjoGk7!;a3h|ug@hn&(x4_wAl;FHd0p>>-p9kU0PD&iiQ#{3n zm!kx~U$0y%!TvnM0mfy9@)%ArjYuXh41^(DGs@!=6V3XW7C@ml$QSG0VNo*H8V49YqU-m)K2GB5NJa zUE&X%yE%?*^4*UD8=2ARI6!tjr#R9obtef?h3;@aKc7aCLjk)*oM61nZImx&VYFP@ zFb^@p^CCgbuDbU%gi026rP6RDv2ZC$TGCHXJL{CNj6;|H;lY2 zqLGYNoCkP1N9!yKDX8d0ksZVljX#YsX**555X}&=Kf@HQBaLF)!7DQJF~S*MI^HS^ zTtBsQVyx>gMroE({47lE5-$?d#M8vh!|4ncX_C%U%0RP|70QDfRBbJN|J!f>7ydKE zu^Wtu;wWf7qtHl}+t(1&toobH{drRHz9@KN7}jl=2NEAs7|KXUcf-FD7T-=2omb>C z=L31_3Z$t%X4gO#1zpmR2n(;NPZYcfuTGHPEk$6+_2Gt%b^~hBlhZ5s>egm*DP?fo z(85r54fot8vfVTeuF;|J%8sh(?51IOFLVu79J!zpMwJhoN)6Nh0Mgy?y@>YYn>Wv? z4`%k1+M8DXOq|NA{{5z4B@VGJsZK*ci^KPWbC{7zWpl=KU9YI!v(JqQPZLh4`F3O zbd9i4KrgEJbgAv#VzJ!-YX8|IfZ9L#0zi#i$$mqAVmT=Hn!YQwa#t4m4Uuhsxmy=o zRWEwIfwtN2w?(P4H8H0+*ruRzivLdo=E)`W>{msBBKb4=#o$_3K?T3O{#$8Bf@=WaJVVu`v0a}lb z_bGvs+mdg`cRkYMA(%C}pAYG=@}(raFZAr>$%AK|c=FuGt>%o6$K(5L%?BUucMqO7 z!=G;RNu=$EX1cyd*t&Qo)^oqncb}$=-ER0vfyE<>ioWS*3;m^5WiZl%tFNgrV6#wT9*er>!ngx6O$M{W@UAVy{kI+c^+w4UQu##8(H4obLh34vc6jFF}5L zz{x}tzGet=osrrA2raSO0dy-u?ZqgxYR4QPr&*EX4i0-7`I^z#MBgJ9P)bzusubm+ zVN_e4jeRQ!DeVjeo*U8x**48h?m`-SZb1V%Ax)%R#U2hF$ErAMSJ2&%zK2x=pYNd% zQZZrZSDVt&bWI@&eA9s@&8>vIkvFyi-!>8Q$CMctctj=WTaKywwr!8B;A*ou$E17Y zjeRG8e#J$rhMB;MF3v`CIPuy?WAsW#g>gcY1KGA`~kiPF$+w)OajObxj zN>S%|G=!8|r#_7FEMCA_m_!&xa~#c*A~B{IXR%93R`@hYmw`{Z(>&W` zL7ycFZG~q^><9A;KOrT^18X|!Zz#S-*#K_1K=bT7N;)m~iXE8%jR^~;Pv9e$!n%RpYB@B}pW9ZgnQAVwV z%reXNBbu>!Op@uC_!%m3j*~PELWYwhje?Z&trl(=u`J6H2YWg8;;9>ti@1oh5Et|s zlQhI}ZbvBMt7cJvV}MD3T{jPC83fsa_&Cb4`3*(T1JI6>EXA`t!q?Xe95R+-%xK9% z;=NC1ahWb~Od>zQd0g^0F1_(8&ekY=PwAR5lCUt&qcqMb^Snjs`;5?8niXsYJh%h} zzDEN%K#r7p&734**jqA|lbj*` z@F$eTIV&hz6j5#$j0Zq~F_*5;;+jQK!FT?qB<|`u%ux(rdX};RW&9}ML1uu6k{q*Q z#$BQD?F}na%$OB=8O;~-B#8@dJ<4uwZwo(9Zlin_6+GIK7G-$jB_w6=X11Ys;(|r6 zb{6A|udqXc*fNg7`2yc?mu?WUSP>zFm$R7W%e3?vi|5HA4?yRhT=N~1W$GOfx&KxB z?hn8IH~J4Da$c6E)Om^~VGNiHeZ+lIfK%uZc!``N29q6R&a)$46qXrZZ;`SLD)=bh z<3#BJ7pfp2K#ZP{q)2J`#|is5wFi}+P_$qN7f>&!OtJzlrVo(OqnuV&p@kXu{sU?6 zgW-aQ2EOIh%n^@52i9E0h4YW0l#?V1p4mt$KW61K#VXi5H~?U?@&OSmAL=`~LjVRI z;I;#fHQq;Az)P!qI^ZB2=jqxbxo}@?TJBFIax4Cy1>PjEF`vXwsA>RhK9Qiu{Hc7r z7*^lMv~t7QJIq7%o=Dbb1W>mrPda&^E#`1asb9UKhXCX1TlbKVc<=L!hlT(NPaknT zo(fzZlaoC^ACE8lQ)6=^&XeC!5>a7ue|NvV2eKOw!iL*bf3;k$?$?9+-hu080oTo3 zZgg_6~+r8E6@6xL)CZ#5#_aCJoy_IVTK0E?^>Ddf-f`=9_kC__yX%>|&Dy%N zmZrHGa9^%A>)xif?Cw^pqq5VwQg(vod)D%54gCWvZKqXlX%6~bv$t98_I$Ui!LZxC zy1Ux~<81(Jyuore7+h@zyIn!6*$SKc2)gmxitYiMb2_h;Mt&(M zM*Bo+yy*zd7ng5(db1u1r$Swuh$n(5o+`D|f2p4;QmZBgGHME1OK7x|)3Z*u*;Kni zr=yFC(p3~wt%+*=Le&JxkUF)7rU}a6Ozbw>mv6*N;jHmaYo3Y{-%XVJ{61BYHBD~T z4CA%fk!qSIjq4|B<283ffT~SUpBG>9zvxlZa{c&;0-+TMb zxhETKReRNKwRBb0-<`C2swyroVnCE3J##YoVz$YjUr4 zWyoqgwO*6-x^8G^ zl5tsYtI|7Fs__)nySgmZq_)^JR7E&fn$6d0U8x&9lorpEplJ2BBpFImP-<#JP{pBI z@77NYo-wswmsD9*B<(^KdmTgQ)uo2kR4xaY-`Cdui>kFGO%&wQx?<>jdv~PQHT6R6 zw=Wg3!Ou|_4DnPI4NVbF#EV8tm(_^|dT7ef5C%=js2f68;de^c^69y5oQbN&pOs&# zf_hm41^${`mn-2{{y81W2XPpL(EbikG&-qz{Dl_3Lh#6=Q{Xa<`3j(a5oA*2n83sG zN1;QoZ<{0l#d2VaQHsKGfLuWBuw&WK0M7v}_|URke^fOc4EethfwU}uLC`HPsPL~! zd=~Sc-{B|-LQu{^0Sb}t6FhZ%WP1VfaR}1(URX(=lMs(4=7_tEL70pN9(TtzJ!@>+ z_QVcc&#BrSVlwgx4=Nl%Z7gVg!CupGFhL`8I&nV095%ad3)kg z&zbDINmjt5<3N~Xifv~^EbRHdja-m4Lu2m0&wU$>fiK7J@T-VN6-kcz{QRvc)W>>N zXTiOc9InoZpDnG>K43(KK$08rY1ef?mJA*j8lbAO6}$MVO5d=*M$=U!~0DA3aHtEP?Bm@<;|%emV3<*cu6@si+S}Ok7|*58@FMr2 zksl#Tl;r8mi)ICL@^uklmX;`s@+?ng-W=bs1mAkuB4trn#4OF@jIlJi<@rmmQ+i!6 z#G<%}L&CChK@oQ&WkJOJ1k~W6@)wuPA#_%tz@9OvC*@wE+{f2`2+TbmNWrIR#cZQR z_*KF~ULh7zH^e?=Bz7Y<3oG7hl=39fGEQjh=iCEapfSHO%=|p1aTsNjIKs)K2#Ug` zBq@1p#kt+Yfh-vN>fr-a~79_{utA{yeS0{s>Cc?h?XygPt``$(ewjwyU~0d&KU=%63Q>67|Y{0!)e zjz$ve2w+CjN^=e%*Oww42M zXuH{64VL$y$~M?+SHt_=c4b`+H`dbZuXmfx9mv0RH}_ZO-Ig!Dzvt%f@0Wbf-c^6M zS@zca!U~vj8*X^j+igKNo%^&km%HV%+XaeT#hTky+Hbuzh|U3RZm{Ot?z;W^tG>Cl zR=f3Jx$0YYJ8QWf@Y_!QGC0i7$>b*%AHDs8-F|rK zKQ1)*j41a-(9dTt{`OZ-@tpS$s_CB;PyfvEx$H4;v_kRtn)ly=JHUp!{q}Z$`P1Xu zM+484-hZ4w`29T{fAu{iw9g)o9y~GqDQm|iU%+(yVaNV)n+sGh9Q;AlFf>hXYb~{2 zyHI;-O{i-%^|yi`%EF0U6KmRQO_GI%TFZY^6B_bGQynzB#Yhtc1w`yyvQ&So{*8p% zLRYNGswlngN}aqWx3q>UDaAjWsr~eH(r(s=y798t{@vx7%5OC+QBvz|S!vblx*)v@ zFKSwUYMithtwBvyPhLs4s;u@K=c@Qt5;UzX*JRxgdZ$g{LhP%OcJ{OC| z^UqISzIdTajVrAt=xsr4D6(P<+d^HEv|dY;HRY`|{Ad5|Uv=6qUA3+%UR%5Pw*&dj ziKgiCD@i#Onueh2Mz^7S)o!(V-@d7zHhS9WFU5C4M}2cT5_;WXS5nSj%Y~#Uovx@T zRGVrivLe1Vj9zD|)n!o|G*odQDaKh(7nOI)xgfNZhN0Iw%Bk|U))NK!-BPYes&J~+ z*QzR>%fdTdzEmzwR9lz1&o8C(R!39hb46YD>bl&iNtaqpks6X*>&WL_^-OQ;%7ELI zPZU*>I-TE$hN9^z66Hosb@WrU){@&&qjOpp+FDIgE=;N3t6vz>TSdD6pK_-ww-r^9 zMuSG1ABWTtjfU224S-OnTj!FlpVnL7ib_r5&rH1zDsnFkS$b1zN}^!2WvQn3)J{w5 zoU{!2QnM_ftqOXh)wYBd0B{6BHDieQPhOkYp$)98s$8-X;3pNvh4_zoG=Z*yrWf#^ z(9Q&)E<7Wf@}MY|0&0j*=#D^!pV+>OJ)2T~ zT!1{1(HIb~=^l~9fPp3I~bvg66X-dB!{A1hnPXY7cu7Fqy>#x3BqIybN85gn|mxx+!UuMj-gT)gy51W!Kpoo_*)@GEN9qdrJp-q z6!9!&9yjIq=?y~x^B@kI#_`h^#0M)BHBT@r?U}ry1cFlo56thTM8Kov~}4&NZR4WRU<54^;5nYg)u# zVHTt$%=sCV%(;t$oW3#7r6 zr#!|iT971Sv4ff82D2c@smn8xW(h+Xbc%%PR~F@j#4L``;&!o!nU&@lREd`3X4rbZ8Q&bXq@fnjj4k~O1M z5v2df9m5EaqmVog$~*W`6;oDas0n|cRr{CeGexyAe}5f8B8WbYp)mIesx>L&JuM9g zW7V$kGA}2t{iLcBFu3tPsC}TQvNzlF0}05_m01N%VSXuplI48=4PTL0Z6FSL$`2r0 zQN`{YYE;o-$0>j4p9I0r(DsTwGPsAr_C^bAxM?VFp`YOorv?^Zt-sQx_uQsZNk?I#sF9>z!b%nt!JA2uBP z@tdj(_76MqNvoef{zy@}q3G&``Bz^Gt8{o2q)Db(D^7yq3>JrBO3f?Od1N3Yydu+D7l}qBStYQ$?r= z@7iA}lBns5BsW?oXTY^GI)=f&N`fpmbV*SZwJ*sMU*6T_n$S|j#!G&qD)(Nhwxmm6 zU&^{9ypm;EYN}mb=<7oNyqDj)FSkv1|UF7}>HjeX(zS%*_*33M!VG=i#1hi=rvuHTgE^=mDGkT z3$L2psi-RQYxQg>)zxNGmXRoG-HxQbI#JIh*>ArT-nLKcZB;kr)2seFNzp`I7q9A# z({aCfs%yG*$#av6Z@L5Fq^>s2@2s**h27 zE%)T5+%@X5sOXY@dD(0ZUa4ndts&})t|_k@VzVyQTWzggle(SOh13;QRk~0$Rk)DU z-+%X8Xg3Kpmk31GfMPcCCIFW}ji?i%3LYcgfry20)h&RAc#3UgTX;_(reP3{0T&A# z&qgSO3d_)R5jFj)%o6ScDik6kAJ8eNyW9hBCI;O#pEv>WDGGoV1$a!wp`sQJ9LpMo zXf&Pz%MCQi#t1{vC-#D|10*{yL^c%1T9c_gCccA1+xGWuIzvCODfOX(6PPj(83c;4 z=>P`BLxf64D5nep>;V+!gd^y&NnPl2$rmB&0PqLWWc=4W@X|)m;=u!@IKBt;ucY4o zR}*)N1eMQ~IGP9H;^0sW3+W81<^w?Ft7u)6J5^Em=p?YAEI07%iDi?(G9BM`gDD8< zL7Py@_eIXss$}taG$9oAy2J-68IQ(??gXPLCT3vqUvMF=l+=KdM+4;WBwLO<2JFxZ zspB{yPq@p&Ko<9nTd4Hn0-g?w`{Q_K1;GI;j#yA&%#VMJ&2Wklng%@gV-vLZMh*%1 z35=#z=!eMX;kw}z%1~|Bbh+DJ=(xUzys^hKV3J@wCZQQtCBoc48}K$9pwI*~&B<2T zgw4>56$nQ`60n#RQA$%9eLZ0w-v4H!?pQ)5A5^tWB$ScNv7_Vk2kH&K5h`GM+5?thr8w>I6 zEq58CVD5OqpIMgM*o$~FmniY`$c*e+;`y1E&yces z#7~`a3iWfCvJB%aNkf*${L!Uxo-w=(9B70P1+%cg>2gMZ#>Qr=2~FoQOY!a8FCsii zNm`^O^jBGwEQBU(ZWeH6}7Uxq&77Vd6h>(}?w+_!fkDUSj$fL%< zGV}STe8kTaF_VQkj%WPGf$y+&mKSkpGe8Ova#-Lnk1>m)f;s%%R&dK+G|%kNr?(+= ze&u^P45*rK7Q=59sWkJjs4fqUy)FT%!_%k?X@89zzA91w*)BWxbzrO2y4tec} zngnI!13*KM(9QP_`@`DJ;5p1TE1?20toTmeBbYNe5~Sii<`Ne433%oKfK>HB0C22~ zKwHgm%hIvS?6|BrKucNW;e!*1pZm0Yj-MUo4{b+N@FRVyZ}#z+9>`z$(c!9qa{sE5 zZ8Iy-Xpf!62cP-1N9tYWU2*(|9+0jlC9-)8M)N%}uHeg_<`GP0)ty#UCWlD(T(CT{ z(IM`~Nl;Zod)65!vc*TT-ZSyFnUnFo;(cALN5FdHM_eN-{+w7#+}>VZ-=Yx?rJc+x3+!$pSd*em(VHI8k*Z}Z@J!Uz4bSh z)Z1#`v2@$rLdQ}b+wiLDSh`zVo7MeQzk9#zZid5s$I@;0{{HT2x$E<2E1fsstC<^X zyV|!Z?Q<8m{d;ItT2a;3z@Mum-g@i540Q7I`2T%;MuXB%4(CI7XSvI zpGI^(8|(Sw!LX0F`hZ*adA@wA(AEBU!H;bJIDPcsA=T5#M_zqWmu<5D?@xple*XBV z=k2H3lKvog@|i5A<&Pm+pG0jweczWBmi`grWA8qwq5V9(?)~?C_p7HIwI5Q2`*HU)zRFc)#s`~Z6lhuxJA*h3!+TVTiji%XxUXw2*Uuh_YRIfJ$QGOw`)Q%|1 z{3XP~6RQ}5eoYm-it$%P@L}UPGExlioGXE+qBj z@}+*Mo-2YXbQM8S`q%ZBCt^crU)MCXX`Cp+l_09VC>vjEs&OVZbh&k^^%ee<3}t;} z@NCF+O;k@WJFR+KJmI-X_|`>Ry^xHiq{{lmul_|#`2Bakoq|Z41&uNtXkIz>F&>W` z-vLoC;_QXhLSoVhqPBx7C9sP0HFn7!3-SOaskGdH$~7TAK_KylEz3g`Tf}ikmLDR( zyZo``g~$v>#PKFU2(1ciC}0GU^{Voe5|f0U1I#c=#vwvgQ6r#RrVqU|@yO*4gv76~ z9%z$*MwFs`D@>0#zFU#803fRxa&lKDBp8_pg#1SVCfEfDINRfU+ZAIRs!ajcn^0ID zgcf`VugYHmJ%Z+&ekJ9GOw2=Yi46dv9oVKBI03lk0^1GhB17y^Hw2Cx_a0hG5Nf(O z0C6^8U?J}J2!TAAJ2KtCvu#xMb1Cw@YFj9wGq2Yga`0q zIC7vcv?BdM-%-z}&_N+YAj-x~n0SgtBNzI*Ldk82p|>cwMLm~i4`kN}zoGgCi~~eN zm-?aYja(O~eWqvfh@e8%!91IwI!B2Wf*>tF1)uK$46*=CE5N3XAGlnM=#WRo2Xq4f6 z5neNzX7dOq^Mav_I#~{kDuTQ$3DW=rP?-da8M(b-i-ZKrlI561ZcfrHtEv&xfZJnp z_7&q_5*D+J(XUG!r;NJ6*HN6N(9tw-C?n+}r?ZsY#w?zvlL!+#&jZX@YG+OW7}{5h zIQ6gRPDEHzL~OpuXC>kxejPKD#~0EWOZf->)Jt(f3+C{95n@HkreR961uEk?PSY?- zS1HuE`aTV3F-vG{;XGh0Lt$K`X_EOdTCxgyjgf!D@=01`Nmf9$XBM!OA4@?BCra4Y zMVXOh2u)W@Mziaj`q_-IEM{!J3g)XM2%|V=bj_}lB=dMe9G~TBkU0xJXET=}Cv+MA zEDa3~W*&=a>crt9WAG+-=21eK<#C_rb&&BbvSkRM8ueL}dWg&@E7N(zlR#(|=Pa31 zew5)YP4m?{$$~hFZdqK=c@dC^rMJa($Oz@j@GOe5^qMCZ4rdyZ$!!7dtRloFNn8T3 z$VlSfq%;KNYZg^3I-JL0z~ZP#QB)+iEO3k2G>aojSRArBF3MRN@lAOy{EQJl_ivJz zh5RW<5}vz)@rRhDN3`re^}qYWucy7wVV$}0UN=80{R%0;)&CU~;y;l(Gs^&=4|^Ov zEx6o+LPb&LfVgB23Sj)W%YBul5BN#dsniBw#;S0gVsE`XfH38=<^|6hWtxXZpg#Z3 z-}e&TuXP{qfuhD_w%_}JG$FnvRCEJ2RoM>`%x6jEZXXV;l2-+>``f@yrN~yDnN0p{zX+1@yPqJVdFFFUIA5$B2e8{807xMI3b6wuZ7C|vZh?%Mwa z(s=#u{_+3-ABzYC000000RIL6LPG)orD^QF%abEnx+mms*E=MIB0`aGg%rXXfq2i8;mV%Fl^Qs3s$fIj6F7H zZ1@Y6{?EQ7{rz>MM_96U`~A?im*sNU+wIn)tunbcUG^rw94JCys&n|)o5?q>-}y!wAN+0UJWk#yZ&Ie>)HF!Xus;Mwu6iH zb~v(EyHUAc_ey&;?DeePpxjtxufN{(?CtuZKd{AgYquIK%iexj_Sc}nE{El=ESIa^ zU@+Pbm&+xH+Fh*I>%LuDn_+2RjMnAFa%1&YmbKZf%H3*pvD%cqTRr53HnF-^?F!>RlVK_2CdfR zcC_yeR-^6O?t$UU)$U?2+FkV5z14Eq{r%7F=k~9v{rS7^{_5Y$Q~GNhNq_bIcl3#7 zKh^nDr%XRMn|-;8&us7Y*iWgMeU1rJ`dOC#1ZN(bGJWLQXSVm@pFJYx3k5&n&QCN^ z`m6u&yI(%h-aXa%cq@N&#J5kJ{UO_X2zDp>7Qu5fgyEk^>*V_($#vi z)vl?!Ch0XpZ_2IiKTvf^G0y63?X-WSD4N#M4P`KFYJ=LjWa!T{P1R&sff-FnHl*hH zD|2YR)a#~X$fly3HO)}eo+e2hLzk_Zq#1^x8m7`V+70cw396K5T~%sozH+3it)8Uz z)H=x0+92*ok`!5O7`WF^Bw4jpRnyz1BIz)%A*p_&`BGJ+=Ah-)bw^RV@`>JRt8MwH zqk$|3x?0mvRsGp(Suqu}*O6rDO}k~*mBCp}F|}uUQ*Ab1X-5+D zYI;ZOHg!`vSCo4FNLN&?bJ00c%+X8pPtG8_oLp8~s#L zYEDa06ysQd5X(n{{8`JXNf3KeGNra5)nu)Y%@adzbbFFkm(`|Wn&$aTKhhx3x@?%T z)R!B-{r3{eZF zPGKUm#x}7%gb*WRf=K935EBhK7$zfzp(F4^N-$g`E~tfueLKJ&0l}0|AAVTO!ie}R zpkNJ|A&i3z9*diBDn8s0bb%BMM<5 zBA_V1Y+}($Kg@G{v6P_9Lg152P(VV8MU19_<+!jM43-#82*%(tOb7x9hC8;1jp)=J zBWyz)#WGSy#Bc1dYU!zWh%Veh81%R#oQyq-jHSQ+{yPrQA|9q5jxJH+WjViMMVxTH z!ibZ&urrtE4xc9hO7m%gQxCH%4hBTb;T|imIE`b@-m;kU`6Wj;UQRQfPg$06nnZ+r zoy~Ln_LAVp7ApcvU7*Nwd00&GVu8JBk|&E*%7SGS+1ClrIGcyjHTFrCBc6gOE+q&> zm~j?yn{e)?4rTKMdtsbLSwt2nA?t`0=xr3DaGp?7(l{Uihgjnf){N5}r96%1eD3B6qdevzzo9Xi^9ZL4 z9#W2rORx|gXh}*P@FHh-797fFj6xMwKF@x#Xu)-nBSVqE2pL6jFVmQ8GDM>g^QX&k6IsSxyjZw(0 zBH|0quZlFKWDajKK3jx{fjqy+i-3a!?voy5f=re@!@h*ctrtY{NiDo72>ilW<(TzR8yG;(Jn}l zRh>l+FRt6+VI`OqKWOvAFSiiyaw*IcVo;G!#dr{b??*;La*+s0DU27*Pwxzb1~G;1 zm@**&49W}P1QWl-fLL4$DrbafVd1@9hnC(S-NmD@A6S|l3@WGy13gIhAPR?RU|MiD z4b#d_VULJnMyfc%oB3@7GY5p-J7(Wbzca)S?@R*~a5zPG3J&_MyK&-29#>A?DFz?? zs%zm!xB73Jy0&B^>+4ZWGz?r-rAH_xx3hJhO2UPVU=ZnIoj>_<#N3p_WQ%tcC{XDtkHUS zF&M3_)o{D&5BGLC+Fz_z>tS!T-*5Ko)x~Bz8Z8HdwY}bK*Vb-zG3*V?p}n*O!Gq@NnSKC3^U#)h%HJE7cm)qrXINELp zqwQ+2w_y5qX^*V!wqLGxtKGg|4%Ykr8jRU&?X6I@9c=fze$QU^F4k)hwcHJMFnYJ^ z4b~%jJzDL`&Cs?t7pr|a=#9#9xEgIntMy=bvD)tU%fYa>?yt(tx;NMk>~gm(F9yru zZfILDcGDYKe>+ge&+X@SXkP$&eJRv2`|#us4`@Ar)IKTvCu#k7(&JZz0e4ZDJ{^t^ z1UxbHw#&Xl*6xOSPskPjoX?Q`NfGwJye~vGe*y>!ZTi@XxOWFXhJ$@6`tbpP^H~7X z7q;@z!w=g}Le@U^?Cqn1zkM*ad|K1DpFH`nm3J1rJIKCs>{CAH)qb{G+I`I9y{;I3DN9xcxeQ`ecQ`eO0M!&5YhGdwdnW{D$ zb91h$nyNQcqgj`ff6+4KuG!FPifYvKU@bS_9IKLMN^kp8W6-Phq<=Zn^yZnIsgg7> z73q~?*38a7)ElyJxqN--bbV+Hevetg(%O`4GlAN*BZG%LqX6TJ0MV1vquIW;0 zN=id{)2!9x+Q}fOOD`M$mZ@rza%xEbvnr|biG0$R)P||m&$QXH-W>GW+FCj_h<>7J zN~bo{UMOv;X`V`&()u&qF#oJ)pQ@5Pd#R7i(ccGIbxBpFOSS&Iryl9jk)j;QYExDE zx^|+p!70llu+xPaqb5PoQPW(c59IIj9-N%bp>3WPMz3z^^~k+f!NBBw1Fc zP2Fh9X4s;xuPaTn(djk14ORZT<}Qw-_FKaq5#DT-N_n#bDT(G1-%ntwIW zlzLk-xSzB~4)MSY*Kka#{NC?q6g@L7WK zIIz(e!zoNdgt_p*EP$R6L^&40bP8iBJQpKRpf~~>V^d7V*bTz5C-9yywBXU-amNe> zk!k3T5m@127)vQ3)nA+7S?GvU<_2iyf~{csbQ)N6Dhx&-g<8Ugu?yCd(54=m+0K~I z!1nQ&;IR{gFo}(Q3N~XL2*l7q0vv=fC?H;i`UGR}#S4gwLR1AJw7?n+ni0ibNJ9_& zg0W*dCRGS$J|-dZQD}wYQ)g^}M*^iHAs88Y$o8i$o%mEpgU22OO8}9=p&t<2cYH#s zhzQWhg}72iJm$bPFwPBpZ;a7+B2X%efOs?xKoIe<=(eek867j^QtZN9-xClh1>azi zVD`+h1@swUf&5{JB?KMxkbuB?;BX47C8RSaz{H1mGlXrhdx|IuVGZHX7gI0=kE;k! zmyM?sqp3hQ3G-(H8G%n>fj7e4f{`x}R)`dw*sxp(Bq3NCe}?>VNCkjK<~&OmoS=+z zp5+l^S1UM-oB-LJ+b+w(1xnE+K`e`-dBkmx-`qrm@F4Oy$5TG1E?Mz3VxB#-Z=Bf0 z9#2A^WhIXn(ai!enh@?eL7v46&T<0M3FT25U9-1wJYgA4q8Vl(M-xt>+~v!3874gC zD1t|Mj!;A~&k`P8BJveMQHec24(SAy91%{q0F^>cV$aS(%6ZN?LE zewAGEgdpExbRKdXhRIFL!TB72?IDgiJWW#`r&){_5m=Gn{5qraMappmfuD0wwOCL- zSp^YIQXKLU(M1wP^Zdq!D1?^@CM@G$amosI1saG)!pq5;Gbc$Ppz#8HxQShqmU+r! zo^T&xnTh2O*~HH&59Wyt%N)Yh>jce{BExwUxjc&&!8`>Y2pGxUMnyt7MG!>SWtlow|IZfxWA7T)n&*w$BNH_=e%aU@EQl7vxuw_vSC~rdIIme4QU+3Td?wjwOX{mk6LLx%bo09vFGwoWf;TAW8?D<^?%`lfFR1=zE|mETTyf zCBjg`4glChfQteFyu-Ih@nO3K*l=7$D!A1r{JQ^=TSiud5&!Iv2;(EHvBR1>f(geFO=qeCzdEJ*eq z%7c?xSbPMtp+{i0|M>G^wj@dDuTq-F(t0iEW2?cax7=-q7t7_KT<*&Leq*n87uJ5b z-Hm#K{%W}E-*LxQ`@OXt3i{VzFx(AB%UyrH>hHJx;jSE5o6+iGy&2i7^|IWrN4?T6 zH)X%tp1oi9E)Mjub-A*7z2VO4t*vsn+zr%RJQE6@L<$Apu z3Vz(C*WYX`t2bPM#@%i>yjb`4%iU@?Tv@`yi)Fsi}guQ%GP*6S_E-dqefgTZ<^ zw6=S2WMHjVgW+fAJ3eA4&?R8Fnvb+{t(9haLy-9o;}@t-|Xt|^s~l(jH;FI z4?YV)`SxRA=G%8anR|3Q@dG%i{6N9GThU*n;8WzXA71>)RzD*C-6N>nBZI!Q)5Mpa+L*@t81px9%*L1uIb0J`M);$on})v8;Y#A8*TNhCD;18CQHvXLze1C zUBys4EmIrTOhq$gNj4=}l@zH~S31XnHKlY^-83atYAer=`VC163`K(TMnl$RU9Fpn zsW%m~)6vgb!=s6zDm9RyYHF_r7PX9qEa|2^Xg9QWya^tA3)+JeQN_9yCW0lrvZLG;hM@@BcKI!OEtyNc#YW=hL@(n>1)SBSDUD+X4IvlntT?j^=Fb~b|-bI*6vCJ>8#U~&B4)`*>0ZI z>Yahot*J(<<2GAzTUOL(bwg24&z0l0rT5O;V6EPl)OsV34Xt;o9GQYfr`B{?YpG_f zXTO$>_N*Z{m8RC|AL&}{8Iq2bcB^YOWbjwlu-+ZWa$7QLr>(ZtQEa^~8HyE2!co7k z=+9e{)_>D7tak0VW}LNcz0qWCU9X>a3{6*#l#`M1U-dLqm(;$dwi>dm$j5C{dRdd} zO7Ge0nr9+KElow0)$W-l*R|)e+L8s?P&ZFiy)lsb&A;q-IyLpbZc3^NH4CxJ3(zj`U1U3g)ds=|ni1p&4n_>VFpMEi6l}&b6gp!DmW94Wrvb4ALCB;)kJa<8X|Fnd=K! zkAgl#TpYlm;2(n75P2MiU>gx|;S9k~L|srIh=r4IOt9q=98M7ulfW_Gw!nBVm>>}l z21dZm;M$V_zCZaBLIi*oayrdpp5z%5xQiEONpczSC`uAOhgk(iCC}r8$0+AGcMe`)%Gz)QbvrKYZ zz&y#ETywifDCJ2;(jS$FppHna!6GohBfY^VE%D)exFvcyfhFFtf;}VTRE%P9ibCh@BkF zON#X7CgzAwBc6f-ByhlD6moDU_m^NLzhoTlgp~3d0#QnMz!6M_5$O$MX&6(n{;<+K zhG%^cU|)t2int%}D97xE$GLlzvg~c{41KYj82 z@4hjfJ%yZAkjRG+SusBVUHKhAv#5Zi@B=L8j;Q2ST(0~8mQ)DYd{SXI6)ZDn2R!P4 zGeK{7ka*8oy2D})%q|)f574Tpx;O(_i5U6-GP`Ye)U;T@G=#hdo9@VS3>40a_zsOi zS#ht*yTflpOW@C8GAJSm47rU+a?qO;Q#i^pArM}*mG9)13MO2hW%t9w`JICS^kkG) z!6@dlLonad%^oy?h8+}!!ubWRB%xc>DL7mgA;>1;a^*%ASJr}Om=y0Jz4z@7tP~O- zf{{tJSXpJsL_|Bj4M%t%6!6)O3fHe#g(6;a0br&@EFwo1_ru6Nz6gS+*)4!ZD(`JZ zAab$L_nzxl_?DX#^Tn)4K7!2t$462wfBX56S;|=as}$ZLrRBaa03~~M(O>SjyG?mf z?nZ)`wi=GCaxmKM_WNyFu1A~RaJ5~Jh8LDK*o;=Aa=R*b!(D&4-!1#Y?P|5zt@oSV zaCI@-jx1=~-F~!PuU5<9u(#b=Fm*jzj_j>1C~3nBP_iud+jVa#m};dpTrUTLi3S&X zFnHBpEtlnRxVHC}Z7+vn_;%G>?|S>)c4=P>hFc3P-|q*44ky@X*5<y&ic$6UQTgwF`FW;(`}Tph zr`mgien204`{l&7caJE%1IYgH+`AvB{^g_YmY>7W`?&j_19y=5dB)#kf$t9EE9gsn zd8xl@XmZO?WvS6J{#23`rK?NQZ`GFEl3vKFq;}O8nyMJmS+`}%bzORMt;ovB`BzfC z(P|A(3{^F2jqXt`Z|RNJ=ogwIt=(bQ)QsmxgR!DYU0qc)Ngp<9ZPZaE>19VUYTd9U z_Y~c3YSNM3e|CBzBU5^IuKHv7*JpBbFf0{as&|!MyWamwmJPEl|DxYi)aElyk|i)u zU_++*-$;^qI%u{Bx~89+FQv7ln+@nTj*OM0H1+UA3Xf~1+Ic2z#>%h1ekmO{2hFBD zZP2FDY_(KfX({r#^p&JiEX#^HsJ&6;cI*Gx{>8uj`x6Cpv|1+}S?adWdl#?OmMN*q z`RQw?FSq1o4IZ)=wkfrC1=5f8J zc8(i$)YVT^>GJ5JE1lN#ntBYOd!Z;&TT?o^URPiJrKEyXd8)|0H*iqzoGE(OGz?in zwVY|HR5R*b{YdM}>Pb@@cDqWgr%KOc{aL5p?ifnbP-=~qZsc9HAxV8*ZN08(?fUU= zzyA&%A(=>d6fnuya{_FSJwbpX@XR`{&=w0(WKH}r4Vg=+?}RpE7-39YOahVX=b)+W zP?63zrYxWoAzMHxcoH&VA?A4Dl#B_yrH*Z9D%fBQ9{XK^I0a+DGNa=#B%wgn0vd*a zk16p94IGzMA_Ld!OCD%A`eafB6thp_Dmau=QWFvJ#QG_Nwon-KVbgP{3dmD^|| zjK)p{RkC30JBZ*3!5(2Y9Ww~EBS1qU(k|I_ETBfwM+3nWvvA>uJdFqD=PN~gPma&uu z0+flb;s{M59wjbMue>mYhuBNZam*>Xy7pNN_7_(%=h=MD(@Q7IG7OTP>oCVS;dvCn z<%P$2%HcksUhYvIlet6Z1&uQ=fd}El4iO^D1z+T78c#Xr3m#r3l<{~G3sTk`6DDA@ zj8h+Rm(wD-p2g{`O#JJZMHGdCVTE&_EFu99ad_2*ZpOit=_M*+@HMxhl=u+@GRH|i zrLh~OQ5fV&Gju0z*NQY5pG8paOmoY$kM16S`xJJ!};$ z799Ycd6F0Lt%US|-rQ#d(js&VH-lje#vq>vY0l!7*i~`1VoOYori(kI>mVt-gJX)> zd#01fz=Rmg7Q(jB7Bd8O%@b1`P!fQz^nd~#@+d1=;4wXbbd^h4@IXGR{-%yVeKPcb zPC#q^G^2D7H5vMs8@cfgI(O6>uVOyK>fNak5_0I|X% zV+DN=E`_s0+z~3$Ab^)ZW!OPqbTBWzBa~d#W`{B@D^?IcR*Or3q zHQa7@>wQ&JY*%r;>~gT%Ra7r~)fZf^<$g4>cI)L}cqkNB_WC`m+*qsL5Ty6*?YiGz z-xUf2+545%v$mp8*g&w!M5VBmz1djyW?x$S^~&z=hSqAcU2X?Ek>A)m(7XgBX03LE za$v9Qa$ojW<$k|gT`c>h1v<;+?!fU{U2J=s-ez+Fa(8QxKU`bGp|#mBcjb1sT$Q`N z)dMw~U2kApWv>UK*SmE&ycli-L(STQ%7L{i%jL!T=Ne%@w?9sM9HRO}@u=xNB=IyZ zao77K3UsgI<55rGOhUB#&;Woyf4@9&Y(Hks-#lCL2LnI0YWi`c9(DO6jdw9T{ZG~NaBKwbLwsT|0%8d5&$%^w-c`jpC_!u_fsDDfpk*5yXs zIC`O)I+7JrYV;*pJ6Dd4QdLAfF74&%8&RdJE%lE~O_mI)+o+$^{;8q9XsR9g)RdK$ zEX9hUn*D~{YaT1cS*@k&QnPNFa{Z+WU&r6HWTky1ncAR!VM>N#YEna2It@u}>XO`% z`m(MoDx5uQNzw~Rf@8C$Ym!ly6!WasR%_?#v8>4Yv7tBGomNfmHwPW5qw2M8SA%a; zol_ZHX|}YlG_!7WyNaY}k~*lX^0_9-<2NI>rJPBop)_>a9Ln96Hc+H?^HslnV#reC zsG-QRq107J(d&w)J~wn-GhV+k8Vy-KZmA9PwE05U)#g>KM+5U!qoqh{r*qQpO^o9+ zO&x;w^?t8)rb~i~WSr>7x@nr7xuR*hteZxy_Y3G!)FbV<(^T>o=0G}mW`h65D^*jw zO?d-!T~ZXSA-9cJdZ*J;+e%Z{TP?FD zDHo>mMyfZZrqO~`B)#?Oq&_hkr%mOhdIpmvsoz$6x}m8$M5LRT3Yn5*}R-q)e?K^k=h~Kene3bc7Cd(|ngOiv}$8L^U%}%gYus zoq%Cju9+x7#-JNpBy`3C`~u~Kc>$XdAzZ*r%sMc}guzVEqXbKh;<4aN`Jie-9gDh- zJ0@XOY)#~$2E?<2F|BH!;R!?yGweg?k?q?eq9T_PZW#~e1pX|57TL{M~+%Xk?e7cQh}l(T>#&izXs#nI{#kqkL8&kEw- z(1^z=4lBoQ;WcMCW<0>zW$JQP%u@Omdp<&JfuhJ~S3#U4 zVVZ#{MTj#T@-QYi_Octs5s0G;&Tk?=TXGsBo(kNDc#A9wlZ@K9%-N-1#vb83xnv|t zqA-IsOCujANrGZGi33j2(xW%m%wEKiNa5o?M>q3Jl^IFZ^5)l7>4r**0#*kEQ({#wfzWOzeFkL%f&V4Gs;~)VQ^oDqBz%8a`Sb@i$FZz zhBQvIe8J=75@9jG^L#;kdz*MD<})wkIbOu@lQCOlaVCVhV3dn_JdYymQBRN&6H>&{ zB`yT}tPJA`VuGbL=P~7kg>eLTQk25$;_C^l>Jk*eZQ zdZ|EO@qqT^!k=k&k3!tzJU?jDA`|l}Y4bZID>#g%2QwD85}gC6kyJdKu)woBeB~C@ zn!i6|nUM4Wb;^xI9%5ePq%t^o0N~6YjFkz4b>Ey@o$L_t zMd8ppvx?jMzLEcFVzTHM%XzHCzt&z1^zZ_ABnwUT~jQ z`_X2!TU)DbZ@V0bnp|bsUk%Ek)gP{RqRjkivk@h^c7xrp-?K)`<=S4aN1`N`U^)$Z zwje+CMLDh!bPg|u18cP3ZOYZwvJbVmE|ze-+YFZdk+rcz1+C?-*X!*r_S@xlzZ{Ni zQH^W4>aVw8;dZ&-Zb!?i9@lL-F2R6WuebgEcD>(@_7_z_uA$uVXx#Lm{r+er1)r{<2~}*;ZMWo3i&a`|0QQ zuc$p)bxYs~(=S63K14g5pIC6+eu!WE09CmMb7o(Z5crsc&tX8_5BV}jeq^-!!wVl; z^7w3#_VAfjOdt2{v5NB#)XhG+@+nxXYM*^$Og_H!ae1vn`KT`fG(JR4o-FD9$yVMo zYaS8#{`7J9g{9oWnXQmM-5F@+RBMEIF;0nB&lj=)M~XP z#gyB1t*87(s&yp;&Xt;gt-w<9rfv*}2CW<8u63leq*GJVo=H+N%G;9KoZU1|o}axj z)Ry$}XxIVk>ZbI%)@jr<{p3tLZb-_p@v^4kW?gS7_4;eO2?qZrIMURUGv`>Ti6ZZV zj^>Ec>@8XCHhYb>UaM)fZ=^0nfb><N^ihd&2hWklK)&b ztdhtrJbhQBiavPe~?MQ}d zwxqfo^uIoW=P6m#;%aHCu9?QOW2rrv8O>Qu?Q8mxA!$uRIchztX-%mit3&mBTdB*Q z4A$!}U^P@nVzo|PRc9>h(y+(p!!fz6@5H|=T(PtsK(cYos3s#5&e6-A+ZpNiUAQ-QgR!C9MH2s>2@U@#6t z$7j?HMOFNYrzKFj32{aJeXt;8;LMl^?23x2_!wLYD7Gz_QPG`Ph^8V<5DPXK@hI~U zbbG!h`mhh5y;C&yrvY+YhVX1ANK%No!fEO`9z6hM$P&MOgzcH_Be6pOt3Fp5voZF_ zbZkup&umPXC{-nrCyDD&H^3kmg$zxoNH-L*^jvpJ!A2xXc+DUhAP$M$1Omi7k^c!U ziF8fRhTDa(iEzyGh$o79v2j(3o{ADu2>GEP_>8IGeu1wZd<9}vWh{=OAWoxslIFZX zPLki?Y{BVO7~+_QaTw=ok6%VqloQ8sghh!cKjBCePnwGiqHF$^BM%3Yknw~&i1W+1 zi1B4UU*s$f15p5-hg_t(al+joXQBpI9NE}&5Qy~`VY0+j5F=c|czL~8a666o^;AGi zHcvAeCD|2TVb1dT+x#j|c^0#)@N$uot7$x;JO;PolJlsT5|LyULBx4l%;O-;5{mg1 z;&e6leK3vtILvsCP{BBw#&ftYg7~tS^E?hG@p8sV92O)?dFb(3Qt)dY#8(_*9fKhp z7u+M4{v3z)70)1I0g7pohz%N|oL?sxY~-w<*rlmWJnr*?VeAmFV1_d8+z2+G6q(K(MV9zZ9$)feg03PGP9h$N$lfHE3(QjoXMU0SlSKkA_a%b(M;XIe z6sHA`R|!psQ`n&Ss-ScZQ4NzY;;s)jf(Sn0lrNG+emO^34tEyEv*nm`HV=}pKtYz$ z%=RyN#<<7lWHI$%QKLnM0-q#;hv-EM25!dStb3J3S?VRs=Xe>VNs@jY=T({gc@Taz z!HK}O7Ad`n5GP3-I7tu+hFo@E0?V?#|J^tL)94APD!RjN(s{*Ma;^I`xIh3Mc?E;e z_jm?6pgZv$G?5lXbeqrRi!M=^{7|haAfne2`EMeZu1Y$iX&|tkJCvlD2}sCG?)Xo_ zfO!RzR4IMAsA`{h1&IYjWZz*d;cX@vxsy?$U6DHx8q!d7&ch19NnlbWNJ;`#3EdC! z-P~Iz9{@E~IjBR8CsyfTaJLlmX`UZ&yifo^x1ibda73N_p*$QG^U68Kgid@wqQHpC z;)9#C3L3nc6Tg_>W-ZP|LHYaI{j(~-#k@dCRf>w-MVj2hX@}@nWvdPY1P|>lDbr5w zOrjM}ZBm4BH5%S!z_h&5ei-6Bh(&@5df;kdu~=#Lpx%Cx7q@AhbNIPf+%DlAf>@Q< z_ijzE@*VGrg9W$9kS7gUmMC{M7?ids zUbX8jmx2JbvqZJ4a(%m3;?};{t@qZpe_!qDK!LKi{oZzWpg^s+1G~Rl@1T2gOM(I+ zt8%kj4SW4{uYa-I!q35Ixn1oBeX*aRb;pESRg|h>wPj+t9B%d(%hld4t=(?9@9#=` zS+0kJfjwI8%E4w?_I8I|6IZL{YAu*bOPDM6Puz=KyQS4H!4DWOc2isp2NfI29`-L* z&L6a{}j&5T@%v%zrp-ZwU3Y@(LO9_|7FP3qXM63e{BBJA4mQ}^y{-U zJS14xA|HR__TzP|zWp+@zZ6IN={2%Gul;ct zRFC9Y{>X#}i+4Za3v9a|`XLjpLcYXzA5HJq+mfjsy>6?mj!~~EX4|M4s@|yAUbhCu zc}qU3s{?6Z=+m0gQctC$bEV#HXv#n{RZ}t=YUAZ`<6Jc~-H_VtQ$^NWsV)Orm=9f-13N?kR(FhLWQp;WDH%CaiUdQI!JRMXT%7UGG~ z?P$%8s~xE)x^yndb?H=8im4q-Ev=7h^05kc!Od5luG+32 zYtE@8jl1fx9xKm`XKgi88$G$%liH4U+-$|N*@l}yS6j8Va-`I>rUCxxrD+UA5w%x! zNr(6y!;RCaOM(VxK&0#KZvFY`>vl!Ua%t#LmtjPzvQ$3xndb)KVRJoEy+{Bz@Q`ZL zs!UW>?uaoMM5>xk?u1}6b`TXDCqj`M5*t;Cf+D*NyP`C@HFIZUP%s&bqT+;l&?~4_ zA{%WgYMCQ6p_V_bszu>oil_kB#-z$dqXO6oEjqSHKyVNs8~X&)Nq|E-#=)5S&S4U^ zDD!86C}oG98wv{57#yKt;EIGbe@bmHJmk2!vw+xM#VVqBEVh><;n<-enus!3D5y4G z48m%^#Y2^NIPhEyCNL`;Qxa5+Dp6A(i@&036}T)c7Kx4&O!@s zMPf6|cbp`1Hy}}#=VDhq#wow@Z+y&@znF8MUwGZn38$S=V|PqXmOKcf6f!mFG-#j zFp*+G5hE7Z9%FtzCn2UOcM6_fCd4fwf|qY;<^|b;m+@u7v(lX>F!Bf)S|BnqkHakvFJ=F!+onmE7lxY{P<03M`-!Kt13`x0@5o0O1vRF*ii97gp1s+7+ANwwfL?+J*J1FsM_{1s`_V`h}!O`s-k~q zFE0E8^{ZgFS&7qoMZVbG@?f)DnNx)!ui_d+6Z9S{Bi8#pDHpL{L3Ia;-r_ycEKY89 z78TBUha!q@yja}jVWOEO+_%9&^bvygPalxKrnd;%ufG66%aiz51jlJq)xKH|m-cEj zSlPR+wd=3oY(HEHWT_lf1h8$nTyJ*$es8z7)*At`ZMGK!YiO;8!`*1V-Hk@W?aDe( zz=q{+x!I1E%l_IH+aiih8JC+)e`gIx!_jiI-d}9{tBc|GVrW?~c|EY!7Xy1$Zp#f^ zS&vqm!KlC5tOkPrwHYqgdl;}AZT5rFw%o&@EeNrD*1+1W*9Yd;#sVX4YqJG$+u_A} zC$?c6t@f*3ufN)D*7mBRe)U$Hk-fI|>(O?*@0Ghj+3S_V<*>gJ{Yz_Y@3*Vvu-pt* zqm3ZB*~{IkB7cqcJ6lk{erA6C-2T|@OZQp)Xm3ONll?yqj(p<$qxNX=@z1SD{=u9N zhx=d1X8U}w?87ijKi&1=fTyB&JH~roZtBtYS@725yIwvL%O|A$gd%A4GdEKFs5H{M zPxgPZ{SaXL(K(M68Gls$k7@o;^%t_(9^C`*@m7BN?5PCEr=Z8%d3P>6wX@=nw#OZR zo2;7Wa!50WT|RWT{87!$*dbQO%tr5m+h9R z=mSZw>CbD9BFT!;)-<(dw3~8WS7cL=hX%F29Cl?x(wnWWKAdPbl4&aadQ+{*MyI9J z+N!BYryaGSoCsdoOHDtLBvsdRK^ii3)i^paFB*DFm0Hffqw2b$YihHlz0uC3*OI9; zk6!5NQD0Y^iY%QT8x8rS)~jn$1N>05BfX`8xcc*!Y|2W1P*e48vwjAq!U$FUi{tN& ztR@}(xvsu^Zpag*qt$w*rfK>>lT@v#c9iC^G@dm(rlM#ks_|c*=ryI;kik2>@wPMU z8m;5H@x6YkE4@ZjZnjR8qnB;X=-SO;M>^8vBk5w$=%zl^UY)%9Q@JygjDI(~kZPiy zeRSM1+jY67ovQM=Zq`-Fl%5@HP0f@w>A0tTRq1>#gntFCT`8S)- zPdhc)eBRei24`ARQF=Bf^(HDCtw!y@j zq0E$4PuBmL+>)nFRgslJ?Ik#1iW2$iF)Y=Ys=|#hH0o(X*QKUyL|m9K z7CR7n0@rZ`#xtIU%$^EF%))Hu3Wk=zh{8}L9}Wp zY9xf>WA!9qgqNww)>$SfrC>WEWqQb@uXs|u)(C!)3%$hG}3f$=sx^5W33rU-d> zCYWGg8MOoIF)Hf4gHBOA$^i$ePJvx9hu{eg#|VsMqUe->xWtZrA$CHG&MKah4+?QW zrgR#D)dGcMGa^zJD`=1eAssswnxIf5YC>Gdgb`eAFX>@nwP1yLM4)@FCpJk8y$N+f z0g(x$&aq)7Ao^m@N9@pQ(?@Veu-gJxxC{Og-xVp9!UJ0{!We^V#2;f+ZFLB%g@~wT zg4PA&D_2>b&BBAAk$P&PvC3dw$A%;aHt}_i_{d^LPXUM0A`cn!6;6pbo8|6LSa zg%Qu=JBW#4+KCpK!5HCA!2;ZbLYcU!Y{cQ&eyi;h4v9IOkCo z&^aRTT3=K=KAwxpU2rodZk%6XPLhmq67e+hRyKq(ozWNt=|nL4;C2ZiG7!Ar4w?F; z^ZoC>`G2NQ)v;pM0X_)B+l;<(1!d$PY(%)Yt5|+u<%AP_i^mj5ATxK!)%=j3N5wAz zO}OF*yvr2$Kyyk8zerh-6?b5ZKfldzv_V>QsQXmJ{sBsP4+)7TsVYU$6fiF~y@05Cn9T@X!3&F5LuLJ|?eF~l^SsxTLxc}i&l7-d8><}#o z#vQ3GFXFs%02e5@4avMnZ)4z8;UuEwc^>-rh0||wp~`Bzk}2X}Nt_5ZG_G7>6+Sp& zh2x68Ln>oj+~IH!Yf>F*z*lhFJ;N<_@0RGkk(n_40ST@ON^*x5iW>u7Wz~{=gg*@) z;7_w#{OOy|$DasJ2>zA$kA-T#!p%@{xO$tN{r|W3Ej^B8+gkCC@GJdDXO`<-PKO=u z{fw8x&WBy@YF~j465WS`4nhZzIN~w@HHQHMw53d0BE90nsUBB=4cl%m}gY95& zBY%z8*TcPp)oL^7k9OE!I zvtfVd-W4mXRjk}??aOL-eLLK&K*MUV+4-x3hSdNH75djTX-hhDQ1dJHxA9M16P z;2gaNQhpBaeA@WuP@`YQ?RrcF{gOE&?J;|w#@QYQ zzQ&W_8^@WgJ?)#lenah=hOU{4u2_nx>dn46v|b;nYS+?xitLyes@v3^hN7ODo6|<` zZL?unhNU;2X-czg3>{sujh7wWGW3q#RU5YXd}0l{%_D1IH*~$(o2W)lHyWm4+J7io%5k0CWZNq8QwF_;?fz;Z4Q?+N$ z*aLN->W-~HJ3cZstvk{kZ9LYT(A1UQ%f`u|X)7mne&L(;i6%GrsNp<4)t$d&sxZ{|Xsi|#UZD_io+P~>4iYoWqbb507 zz8dH!s%bpy%3s=`(Xe&3Yv^jthoW&D;&_Valm!vSWI}Mv=}ew96Gr4W*qMuP6d@{4 zn3HKhA*~KXr3m9wN@onXE)<0zWW_@q*4!G-i9B@i$*eAj7r}=psIU7`M42CQn($zT zNle@*0rVpQo)vc|z?}jOa0+GQ7+_A5h=9malwgV`gu3B0q<}JooJZ4rHlOdK84Ht1 zh%n|;7R3|=fi&czDMJaP805KYcGqN*AYSvj7>i*=B$C^t_n|75O*_o`WDe=&j4)5l1))W-$%q zTN2gzmM%z@d%h1!T_MH9O%RE(n=sjzkOV~@ck}!z~#u2NrDUjX*4JvBld@c`Ve7+VU!#o9ns`Lu- z2Qj}$ML^!MrF_Z~l!*`o#DS>Ab03$PD1t?i6?s_+kPa{W?-r?;&;61?jX^F_kzhex z`RD;tO9odiWRB%BGhF%aa200K$qeOwv4}_!kSlp!CnAh0A(9fZ{y591G%`NN|OubNPf~gZ6wQl<#4uJ)Nh< zkMg}tcb?3#yjtw(Q8koR$`>H(?aJ=8l2pNK9+Mj_KWcor4D%(cXF6o7?bF`~=I>FS zxMuyxC{%kX@w$p0bS~?{d;qk>@j;_0+`9%46t2f7%dkqJ3kUZOkvY(UYS4u)?&6p2 z!5w;!M}}aceLh~gmp5nc9pCepf<4Sb-5L`rmK6I3e%1lEV~{Sm*azhh*!`yD5rL9_ zwSakbC!G${`mj4W{BV~U32Qrd*_psjW5pg%x~um0UK7l(-HSr9cz_H2kN!hkX!{Mg z5M^op2P!|%h_c=7M*hY<+W6joL-+RfcD3H#j0U64ZUb1*@VYKb2YjT> z_|{*K)}!n3db7RW++N?Vc5B&Z$CBV4>^3J znvitRq}mtb8=dvtT_5DAM#Gz17(c!l-3-U;)$Mo$mH7sno14D$XajmypvQjeUf;-m zx9bszP_1rPV|i}~Mfi62h)CnjZYvF34~Co3%Iyz^!_n$yAlEn?oo%n7;^6i5V6z?# zuYn-tuXpR!cIA$1Au1pv4TgU+puw;0Z(Dl^1NrX{{+|^jy1V_=pvog6;}6EZSI7P| zmho*U#|Oprk1l!B>EzyxM?j6)gBKrZCEW|rqxg_tk9%}|4=1>X-uT|njeS18A9?;M zX{yKGdHz=`qI+LaQn0?gceS>AzmjspnQM=zLDCqdI%yss-*OVvTWa$VD=F- z^5N3z?b{!J^TGE=*6`zl7axH}s}FY{O*CB9ogb|DUe6DJ*8LTK|KnHbpFd{sQ=xgB z6ic(3M@LnilxCeMUDF(xTBG;Ua=M18oOVY;MR|T=wU1sa$_szn=o(E$ zHFevv3|rUEp6R`&;yH$LV!R1Ej@s^B+UD;x(^NYrj;0$!y{WX6Ue9rQiY{jyKe5as z?eFM{@v0+xDSi82fX0$yXtsUwOf&3WQ)|C5l@~8GrJ;6={?mWiP_^KVrE8t$-~Hp! zc3_z5zZ?4R{-gX@R-W0-*G5xS17~Cz$L+yFk*iQt^~5}WqWoW7(N3C{42YrVw5dI@ zRUIAaBN>u2<&DJ$8jYLEaB8d1l$Q0w(KEfHS&m}K5kK0eN6(GlYfk^)zkJ#58Tv~N zs`$y9%8}NvyH@kXGu`r)Vc&jk=t`%1qFMIoNnf>X`|Xtssba|cieuZl3|7-o)T6dy z*&Rc1K#=LpiCl9-Y2}JxHCy^?Lp7D=A@(WABVpo^ zgiZrQG2j~r$V3EqE$$?NM6qN-sWdfVP*~076bj+Z!YK-3d2&rAgoQ3hV}tlM^$Cz_ z5DjNEnK8sTn?{&=6Ug$yQ$l<>RR9PP4-$C}kH{>TB$&+niR(^WITHbWDHb8(;gEve z1cg3iq=EkV6k$4}gi32}M16UWkci<3vhsi)Bmcu*IFbH)P(zM$0+LM(^vps3ijhzT zGIFI~Sgt9INlbAN$u*K%VF{GX<=Ws92uy`C2qbYsd8j9z=YgPkQVEHniY5ce1ah!GHvLLTvHJaZB7zGUQMpAsDSIAO6| z4vw%3d?LWkVplpfiTs);1oR;3GIbM-KpP$aEsWwQ#xZlD_8nriuogv06qCfKGGG&& z_)(pOD97vto^VNWk;#qasXXsz^VK}X(fkrbazF!|#Nkzj%Vkx_t_h2TClD}(78@K~ zCVVb3RK;Ofh_iALiWKp8G^UpUzJ$E6Y>_h&rI{c>S_0n&AcFKQ5K4qVXmLT##o~(1 zQ*p_XT1`7E$_wenQbh7d#l_oPh)kZ?ys}!RsmrREXICP-I2U}H@JjGp8WIItgzPG> zM3QktQ(llo3d-m}Z=sQ#i_RcnjeI99vJ|A#y*L$!pZh#YBf-k==F~gqEEWl&B6bDK zG8RtrOZfy(5z2~nm@&G!NCgodr6LcCoXuH&8I)9{h2RlFBqeCUgov<=TFG)+=42kt z{fZa7jH;zz%f<9Ozu@u@vJxd`h|7?^!x@i6SeAkYAXtvml*b{cFOi_2#d(Gi7xbKp zWhGMSAHg|8D_VszMrCv<_^OI?kyquMgqX04IIoH_#zOcd;blc>h8CEJjL-$bDWU0i zB8!NOP~v4GE@bFdiI|1)d6G-(RVf%bKj&$bVS-W)Vp(n}GB0OtCc+#S%ap_^E<`~q zCNC7LixpoI67V}bCr3a1>4*OleIC!LPx^JP5>MYVZRU{rwOqQMJg?`613d^#XR{@w zJ?(LbJrf8MIMgQ}u!^{TRb|T<#CxjcKHF*!LF};`zyU%Gzo~!E(mtzefwH>j-EtAk zFbHM8S9=00WL|?D(Q=;*#dsCfWSgKUl6*<_hIm+bvR70AYLUyomjl329VC#F8i+{u z7)iX?LlkoEtf-L>>Gu4CU^-pmJ#JFeU{hM(kz<4DK823l_YVLr9Mo_JuaTw2J}C2# za{BH>n3AMAkegDdu9p{gm~8Dgbff+a$TJOw!_|5>fE=;2ZLQ6;C-M$=&USyW49Z_iP61?ZCYqto+S(BX4iV!_j6Wdx9{NyXp7c>;B-@?GFZH*LQcr z0U$2xRe!YG$d{w-p+4PawHgjqx1*b(d*<%^)!BBt?XP#6>zzLy`kSG9vynsG?RK*o zZq7E_)uum`hPJmWcR0ERO(v*N*B`IWb~m*q(`w!CpIu)c6q)*UeLA_eoxfQPfP}PK zjc+%%a@GCeV6^eKH?ACXHoBH>-(25-_03>-HkMBOjhy^{ZGY?AV;rBqdRe#k?VD4_ z>Q+mYeq!)_IAf1b{2ZG3giQ7$?Gx+qnE$OZOLy%K--r&T!OjfCiK08{CZGBD-TO>P zKe3AFEAsDr??X_&ES&XN3qCb&_VCT@y_I{pZXZ|Ndr$QFB);(NN1OvW>^nRp!hEftpXm3gQgC0XH}?e>K6C3)#?jBZ{CH2J z=u5$P+}bC(NZ)_l>+a|G_ulXEw2wO0;17HSX(*0v@E2V}x1l7QV>?}^|4dgkz2AQ2 zbccQ8xT_h4uDApB$&ocyj;vQFuXWW?8-W3}>ujZ?nol*Q)6@)ARZkQEUX0WBYt6D% zMeXUD1{@+))f=jr_D*T<=SQwNI?s9saaMq*yx>78=5Uk$-8pRjkcoqbfa&W zX2Ut|^apC=xQDb8hO7FYB)&vpB$rZ*H#v$(2v zjIQq3ayxakqnJa@>Ara;w`|bWn)=W^eKs=(ivCK|y1&&%>S^2V4h&Q48j7Q8fBDnz zlQ^U(@(A$|0!F%q${%kOT!@9LiY|hG;@2ki+CrV3x!b zqlAOx5EOn3(F{#7nnal5s1_p!uRPZcqtFi`NRpx$<0KBC#2ik1D3QfDo)Q#CK2*Vz z$8*U30-PlAXO!R&^p5D+tMeK0_ zNI*6(q27HqpQhqnj&i=_B)#NmfW_qnszRO;kEM{WwM^e7B3Pdb`IUoY@&QeSNTyg2 zl%*)AJdLG25rZzd4}#nXr{(-=A$Nggo_ql3f>+r>5aMU^l=Hb*aKUoAUCc!#h^SI= zjut86JY7}gGR_xNkmNkTh_EY={jL_?Dq}KW^K@Aj=OoO|S&WuKx`%{(Vl!5xtYYUv zr1Q-MOYznGidLYEl%)|8OOf%QC`HOeo)hUpA|C=FJa9%jkW!LC1;(PxQAUKw%8W*t z$VgO4Kl6$OKIH;umv1vB#8N(oqM8?(@Ip^q2u9~f##1EaMGB%rrHAF?T4m>HCJH1^ z*q#vbjEbP5AI~oEg($?FmLZwTM{mI+l2nV!d>u34df7TovZ=q2Pb)?XDt#^Hpx7j` z7-u*e9M9)fc?TB#H}cb; ze)vb|vtZHU4vr}HScgA7XiC#P#FE^l0^#CNgbtS!9g}Zz$F#FqZ_4wHp%Cq z#&^njodrdg<=v>gIQXG&o*kf@8t2((Z_W4k$dbFUg?ioviC0@(9fDoMV5zqDWv zd{qE&d1McdEf_ukY18FifIO{Zi}#_qYX`@IXwM_6C4c0k{@zJ|=MHdJjZCEnpB9Ip z6(BP1EhB(+Y6CgG)0c`6t?G&9CG5j8iVyD8p+N@~@AvikAeZlbYGAgYHMmD%4Rwza zIA8CTm9qUTce3H~dBH5HqqE=-z@y0{;L&ft0X$;z*B|7+1q7sthPSKT#@~!x|MsjV z0j+&t0YNs`U=7MdqdRG$QO%_}TMuu?>mek2UEi$6K)|_iH`~#0dpp_z4QM=s%5>YC z(R%Cd*6TB10qxeCYdONd_0Qb#&Dy`&^lx|9>+QJa09{|NH(Pf*=^zmNgJn ziqE4PkE0piKX&zzzaOrxQ<9HrT^bX{-#rqi-Ir~g#M<3{#@)BUDXHWZms|m=Esy*#EW~15E zUyU?FTejMY-nDe~>EQT(*@~`NhSoQZJAJj$Q;inSbxg-F6!-Gx-n76Q}W9Q7@i1+vDef zs<#ZyXZqEo z>TT6%o@z~CAGNfj=Z@BCc1@%I!nCxOMYrhHb$){U9+hUl;>ur`EQ4g zZZ{jsk!3bbWvFRWY&gz|rWy@J{-uSj6y5p73H8L?pm7I*p*5nEW>)=266hAc$iWCX?ATo+OD&=?qGlP0&GoX2yLU z5KIu4wxIBs{ICqCl8u%_KbIX2+OgP2ZOK<{t zRdf>0K!Td`#D)3M#78krVuYiF)yx}2apF!H!hnRq z)V8N#EcY9Bl_%0T@W6-*JRk~*Zro1-BxkRMg+#K57bz8UVDnJ4NG?F2CKKR99F-yy zUbbGmgTy|BL!KiVi&(f~;YNba1)qyz&b||6f=ZO;IVeSoRk?|nNW+DEzKVCi8Cnny zTGbpRfo4U9#X@j#DR_!6%ecaqNyrx!Peme966Gajes*45ipffx)11r;5LS-Zii#yF zGfc~p3hWi3OJ_`kl}LTip5|Pf6M=DYvB3cxGwdqH#k;G8 zCuEnxAvwW@0X%6NZDSAVkIytl3~o)B793kPSUV)<18pQg@1*iavzs&Tqb!X<3{-cLp{7pJQpMuX)G2*B=S|B zlM4hw@A<6G* z-UA>MENUz&t`=+$SuD%L-2(wBTKYB9XPJVy^c2fq<)Lbs%a-#4KCyI{MOe$@$SI>5 zWQl?0G+$IT2d7%HIa`u6#TiTMdG^-hWKWghhXw7aPc>BruEhzYk0B^=Cyg)Y0fMT1 zJ|sqwJw}osZ;t>i{Q{!m@8gu9J)#sYOKDrqTuUgS_li82daN!ommQ>qKz@fWYk+Jo z!UR@aQuDZ$2V{=XdZp=JTFEsFlRe}Z z{gX!$#TMTH6LFf7KTuv!s@&d=Zr7{T^=N&w9YdDaaJSk5#mIGUM}2v#E&zAE8@Q|6 z@vZM~w_~W=cD>nijKu#VY2o6Ebx6Sq%s72eG-Ed#>ZLoH)M=Ku`t_LfBuU;b11&FI z)Ai4Orpf$gfGGYd?bC41&mkG_{ZH@S`_HsrAUYI1;?Mhez5;prtQz&~5spvzNPgGj zTlbYDu@7_XQJ(J~C)_;NzQ3Qj^~nJr-}v#*tx@xh?dvnlKCoTBfAs!?_6t__7>EFo zKyJUZdhp_N;~#JJ(CA>j+MAwbHdIY*=xt?S*eA;A6X!cqS6YgK8lw}l`&?0)mZ?}~-)w7YyFYB{ zmj3co@7c!6P+LceZYpoiRb^!MG~MbnTTRpc*F)7-^oC_Lx{je3W(1w)&T96LR9l@qvpUCG!&J&<|B0p#v}Y~NY?``sU3+ruG@h$Yz@MDHD2)EG zld;yRab%lTyWcRHX1hJ?8D0CN)%*)j|D9oUrsc`ddNXQ|yME7fRLgXX)4pn`PhR|m zrD~=T+uFcZI)2aYciX0>j%8eI&1~q#xS{l47@DeRs^0Dx%HYlDwdu4QYNOX5wM^AI zHlMdu^QrYl)fL_8{;pwYZRM%)!g@YFe%`T_XYaZ%m7W0FbdD^`?mU0qlN$Ta^j6u{p>08RhsdP+jS@zN3g?6HA zwqf;Dv!yiTzNpHJk$$XL?y08tbs3kJSsP#+%~EHoIk5FN9rZ|8wZ5+W2_P2?$U8vr;a~yI{WxNT0%U=c=|nn!q!)xmC`17P zO=)@8pG|9CPY@D<{vB{4~+kTb?v zfB>H&0q9as2qiNz3F3sZIGBLiHNg{_;5hK6*qcp)pw<(@Bx00A(^xLvXL5!a0}UR3 zLMAAX>%mhQkr@<4^O6{7LrH=H7icvU&t{w;SFSUj#go|eP&`W}F+wDva&ciyAz@5* z4JaW~*Mo|0SO%6%q54?pxxye4Yc20mqO<#&E%6fwBq-;tE!sr-ELIjhF{lGm^>k z_p*?Eb0OvxyW&xr%E(30c`}!$_oEaTn7pb_sTxM8AO03E$ z$(M@~i8$t2=1V)kK@*pY2#TYTb6V!H5LvcBv7d#4fZ{cw0!M-c^GgtI&eIZ;l8F#k z0*RzRa!4lq$Wu?goh5f9LxP-bSW}%C1P|XILI^ed=bdgf0fg;xGZvl=sXaYQx<1D zO|o+;y#tNC*=pm!BkZT9(UgOsj%>(bA0< zycE@P4%G)Uc5#Qk{HN@vKmG6{{|x$q?+(<(K8Z-aC3AUBPZofv#QQ9u8lkAFy92#E zs23SfL-u$JoZI*6%=J0Hs#At)EMtE`K9|)2V32b#QeT~w?{StG@{HaSf9Am~0f3_h zDr!`R?HNA^7kjEo3C2@aV=a6c-1#I8hSR+uO+GtFCPP^<_?7Pym9kot8r<+}$c6G6 z0isZytOigfdt>;p)Ixgbv7}rsfHM=nr|9q{T9mbW(gz;YG@4}~XX4UQK3ih127ly- z`Z7;I3c0qoU&i!+UdR}QX$=r@$d-ddv-#4)O9D#Gv)b?sW+0^I*DU$_U>ELQ?x=+F zVm=G`a*u!HIrv@$OOR43_G}*XVNQzc-+65ZLqZq@Cpau*UUQJhKDsolHHemwUKbql z$kIJer@%GjQq>E7fU*34GzHRJlkfllABzYC000000RIL6LPG)o2yyJaS&t*jni!V* z!nMd^Rk3b0u7&(*QV7EW}Nl}p68MJGq%atM%61PF#Dx-dtRa2RGyOW;fW4*B7IMJFzzxv)=+FcXMOA+l$e7TW^Qs-F^q$4tBf4#IEm7*WIcA*oVfL9J-*qyYv6e>x&G}><)`xhWciafzx?&TKQH1x zC#mr3?|&KJ7w7hmJBxqZ;>GSe=*`h*FnoB+fB%m6w*BM9{qWTJ;7W7o!nfzg&O6ZF z9nzWmIoR(L_Bjgv4T|SZ!q41xegNJt=x}xm?|s-075BlbKZFMU5q|w2{qkq`rM~_1 z-J75NxaG~y-ZbCu&g;)re(bEiZ}r`0aeYwg53V!--qg+K%{wTs?&|P6k5g7Za{MEf z`ptKr=k4q9enE%L?fT;jpOnv0^K~?E9Kv7zOIMFikGrS()4yZNM;)Op>RmzTbQD<-^1jhlH1X^| z7oKYEv1-c7iDt<5v3Oy0H1Xw;swnL!Uw0 zj=Q~%-rF7Pl9{wj#W>ZBW3?^(bs`wGER6=LaJ=~EvaBDeZCwydL06?Jp0tD+go?e23do^_uMTB;&kcPDz!QO}LmsdyqPUE@OV4DDRj z+9!gjb#?Q+BbwUuR8h_c#y5thO41(>fhFbgSbwgnTD#q|PKCax%9?6)jaEX@Ve|1FfwHvL=W< zO*TcSEcg3>udnsaT4S@*5nn5crgo=if_mQ5B(ZB5tO$HUf3y(688 zk~wJ~%m1F#GIhx_PE_4)tGy?(r2pmjzod8?dz3~#jYCSX9YvuX5==uljcJ_NQ%s`B zB~CQ;!WbiL*~pG5f_A!4WtuKgISCs-;KivS$^ny7VwI!B#2|= z0Ou55B`9$*ra=Tefn+?Fkc6{=eFqVrBFAm zWo*X$EMF4FSW4NNt(Y4ueV=%9C!pbym5h~iv7&Uz@^s4Ph(g;aVYHej*I7#Ag1Bi~ zgiw#=K+IKsl{5b`p-Vasos6NB(K1XC!+DfZ#)2ZgLaaiI!b(bZna!aCWLcanDaJ(+ zOo4OH#5lxMD>X1eeL>^;HV=#+Nxz;FfcMnX__%qh-Ei zH6t-y%`=h|0S?&JGF>GzFOBCo&*AoTRkM_(T>tZ!`3Xh^u1U7aX}Wk_#PRhd&A8xZ zKw=CX@+zST&;^X;*^Ff@iy{nPEMQ3h@6vNHB9M3-=242-Wt3O5m@J$E1_Opl>?cJT zx)}}K6oJ;~5d#o_JtL%~d9_|-&@<9YHZN&~SRBLsML-Y=q9mOs!aw@Quf*^F!Ou_2 z?|<|2zsY{{kJkSX9-hMM|MS1O{=NUhz5Z`6|JC*EfBl>5-+ceeDz7T1YDxqjyQ1)2 zR%Ko#VO1?EKO+2ATvm4lg;1&Ts%ln*cUOWcsH(JzD<4_}6^@$9MHSw+sb=t5-X0R( zc7fn%isogt!1wpx72YlZB3%A);E-R+c_mH@p#Ykf6j1vy(2L=dB!HjO&zsJmsdo#j zq;o(GLaLk;j@*JXM{k*hTGf5M>K6FDESl?4NjXfA(43=m(%VWLpjV-$Rt&`Xl^a!& zSIw8eV^F0zZ?SCJE#^Q?QqA+EqG2PGDlRJA9B?>@f5mqg@Bda&5NB`24Rzf+a!aUz zZ=nEv(cRG!gu|7VFB8<4bs>tu@ zsFErF%b{2Pta7i^(MR$s=ra+G8L+$*nI>v28VZtL-OH-Vb#`oca8hkLlNzZujvz#I)m zo6UH*sR!G^#r|eE9J!mDy58(JqjfzP?>B?(MGdfS#?X8-sMm+_Ze(91&(|KhO{5Jb3s4xX(d!eh516z2mpYW*`0i%HsY&FN^=l zl^@Sxcgu_SnS1|llploY1MkwKPKMvz-|(IT9(4cQAN)X%S^Wd+ ze_H*=b3oOPVEA#dd>s{ESsH&5|HYxVbXk!lSrGL>PlKNwx*#cPUp;yyXam*Il+ke? zew~=g6S*Uf6xBSIq>g0tg_C2=(1wO+bi0yi_RXI3T#%I!Ko|`={Z8woqjxRE)mkqE zMVC!gY01y~$D$%?f^pn3MZK?1^|Mn|IMMZqsLCy+t!PH8dnC7xB&8)Pn(C;AuBeJG znJ0oIY5jpH8HOSrNuns5fDBNz&*iSlkB*dHPp}11`=;MJ>&VJU&lsLrU8ScRlg_wh z>cX(qX$eM0YMWYSDjiD$mb5edv@1W8MYTJXJMvH-$s_YA{&w(87z+I-g3wWfk=%MB zwt7-mmt|Qv?+U~5#WzW4o-0QuPfe`L;}@Fo#OU`0wSS>VYES(GGZ!@Oqv;%JVy8XS zkJY{?31YYZ%#d|m6HFkx)iRCHRs?x1wj!l1pY=ef;y^g-JQKR6+#P75+E$c-sH%$K zin=NrivFF}k@eHT$v~7rLNAA^*-~`n+=QBjY-penrTz4U&=D1R3}Qaf29hd02Qad! z3DTdATQZQ*HdM7INTy=A zFO6c?i4)|~z_%@z#00y(7x@4>uwCL|+lw%^V@@NGj6)JfE(#pqCN52)z`~7FYDSX; z&Z!OXJ>ba#2}ERy@yw423PA#m(+1cMo!G)b5=C%IFwg+)Xhbb5a6h4e1AqXZN8!5d29{4iB3yhRp9En9 z@{DZa^9L+<OZ|iQ{rV6i64r8$Ph$QVW?DCRz+m}FVb(mct7< zDI@bGin2wxNK=%Qh|Pew$j?y*uV(WZ{2}bp4-3SA!MZH7gyFa(?1BN;SMhuqWD&^| z8m{827~WQsJS*lU2#IBsVOBc^0OTmoTQO2@sdzRJH3e`(cT^zFlWR;g7;{soy zqFB)d9}`%*%A=C8uwVi5Upr+PGm6-^th!z=R?q|_gkqYZ=+ZBcQxJEtyei`?o8$FW zS)yPb!7D#N&z*P)7K@S%Vc7~ShOU4c%1~P7@x7PmpD(`u&Cf5(&v}U&&qCgK3Yt#^ zgIBc-8(&7_yRaLFi1p5i1H(~M_0GT2_#7H{!nE=4Ebsj;KKE%X-?}OIciQ+y0%$sa z>yn8Vw?3NY1mDuolqJc+TR7}G)7r!jX5#X;j4 zs)9VL^7o+K`pjrU%Do>3HAGhth$;sqI7`4Yy>F)bR(3!m4qqxVGPRdyqO4l7zT z6it^6tYrZGrKESf`HlFCdx2&Rj}E>^9cAxaQ=GOXX(|)0x_ixWS7Dk|OWN>}E|%3> zVKto33gR_>q@rOHZhztz`rngJ{X+j*`+C1nMiTlfnipj(tZ%lP$$DRJclHhUzgrDKCIpGZnL?$*&GfxhkCpj zPj(mU!Fpux_6Hubv>p$}yZyy>akFXAUhgJ{i9Oox4~G$tOuDfThl}m#;;^+3yYa`_a&a#%rK>Uyp!)`*5=!Z?>CJ<51gg#*IU5%!#}ijNILJ zFdTqDfTwNU_|w+*a0}XU>(PFEv#|%80dTh7ZVn*o&H6BO*S5VKZztQ$a61IG-0U}_ z&4yFG1=-d%Fna(!kA^kqcD+9U?(t|n*^LK0(##(0H~X6Fd_1;qxF_wfvB&HBV!YoU z>h-Q3457k-+rZ6eQ-GujOf7wgdtz!{IYFLH30Om_Afv<7nCkJh`vcsL%eCu=|sq--t*^>}bt zgZZsNXA|3=++2(S$Npvm)YR*-%?)ciSPwy|^~QF&0}@OROa!F48G|t%cIz8x3W@`Z zIo#Bn!*&RLfl~(B8M*txeh8A|Z0@#Tsx?5m*{*lv!_8=0*OL*LkiDJkw})Ll9uI(m zEhuaPGP6OODUpUO|=r}9(zx2k+*cH^^!d;C8Lv*nSeA5H^2?$e)s zy>I-77T^C6u?PP?m~QxL&-~ZTY0N(2@^Pk}_>*ag*%xAU9|z{Wz3qRFPUoY)pPOfS z2+rH;&WE)g0`r5WJe+qe9;g4a5NG#QoKG%(*!D|w-RZ>ru>HdmNS}rHyM-D*2<+?Q zq`y>;6Ll9G{v}WkvHazEIp>prb@#DWpQGagAinc9qWx>j$F)Cc{aA%h1^CI8hh)sh z87{C7!u!93^M~F3LfyCOa{1xxhfMzl;U~uWP%jD|#Q8Cn_ga1h0k<9BiGzn$D!AT< zFg~4EcHez}umklU+zk0g# z>!uOwkE(s1>5q_qX43f0eUnGfzWsXhIfg!&Q~nH758e9ilY_^ncz@75bp5Wy?`S69 z-8X)}R{g-ym*}eB`}0uyM_YVcez&DA4+8u8)fr!^$BDX?&=))1XAR&ptv+f8J@65t z>POLhB)m7D^xCf=<1_Fcs_@-o6~ElHsdN_)@_yw{g!MHGXTGw0O2d17`b~rT>mxzF z`&3159yop&=f_;uAKv~#xm_&uT|?}rg8pdH)TbQ1H)MQZAz#4UM0xP}15wiC&aohA zMsKDHQqONmnxgBn-tV*}Rn~~4iN~60XomVs2wxex&@~N7)Me9>jHi6|U+kWAyQZ!x ze`w0WvGGLhii&P_bX6L46+?Tb%FmtuNfmTiP((q{jE*GfwIiy+i78t>39g2+X)51o zqIe`e3*|{iOpg^)H-wHk>yOR^LzR!u+bYninW7}}I22KkI{K<5p8UP8@my-R&&2I& zB!8o5igQAb)PL1gdSakwk}Mt_Y3g&mMFiFC_jJ)# z+M+yuqj!3;s+i=Ti9^Mh$cFy(i7K6(8@&_NXg$$PL6)QwsM{5;r036`8;YWyIt75Cy5!&66vio-d?VolO@ue|_CgO#m3cX4_`tzR&lH3`XsxIlGG|*ky1h%Ck z`B<<-$?T>bdGu$ereL-}EK;v4iV6>BF*KnqJnf99%2QDs9BFdx@rZlGst6sb(fgMpx7nRWtPQk!ZArN?(>VT@g%i zs`Or|ZCO$kM*xi|U=*UP&N{LzTD_;xVq%y>*;U}Cptd`TF13Z;ABe-YB1zBtlK!N9 z{zQDCD)RHLpu8;Ff}r$uV<;#+Y1mVg6LV&1k|LiAElt$Bx&&(1mE}m3uf%Ta!~|S$ z{#@xkkHH`L?qND!YXlA=3>0uq=$43{k2D*^H5k~Ug1@rBJ&NN9jg`;!7FZjYp0)y>}k)fzm- zR{*!&x-`2Nqhq5rQ-1LaQ9{DN{IebiVmc$=3cdEI?)FXbsjR;++8|a<{hvF^P*kLj z&{O;EmL^MrYKRk6d@i1w!bR5B;jKPFH*)Nl%rRdhcj0 z2q&5@iBjwMxnjtjXQlwmWx6@)y!ykVD-n!FYAG}5+AX7Nb`4b$#J*;lqMDtUPsCGc ztT{e(<-h#?mu^I;Ls4YMGaCCCUi}i6#3&AMLg*}s{V9$tkI>K!!T{TJ8crz<0-Gch z1(wUho&prx35pXZ!akXin9g_{TI?lBNUfMq;#oLEO{^KeVZ}*6;6@b9rXi*-_MtgO zoDkdN>jc9fi1-RSFGMc2`Qkk*!ZERN46QMxB#hCN$5g?KZWv;~3KUz=&~qa?#W5w= ziz5=iw;Kl3$8ZOziYy*57xF+aN*tiuA(R3?h%cVxp;Uy-01N`!fPHEQgs<{TVoEU% zC?Os+i<5{_9)(3{VsS(ywqt}6nxG`|3BLhgV#`O+EOcoQMN{gAm;hAx5C43MBL^^s zJoX0hU@ab^XU`nIM$-2HVzXRv79kS&d^IGAKvtL#zU-3+_SsXyeY_Nb91|Yk#TUu} zUVaMKBQN$q&_G-SZ}B{+Eh1#fqv$|jNrDrHV1#W%(3E1%P8^0j`j6Ut0prvm2!uR~ zdF)u&08bJ>gr>yet0yTAqaY*!CDG6m`ZLJ(ONk2#|r#Q`9uiJ!!HM(i2o zYjZ;$Lx?OpK%p0bo~I-vegu}vV;ixBXv8}S7#7Go;eMU~`JU@|f#+ZlIk!r_#umB{ z7_tQ?yzeH+4?-FNMCcF}m@b)F)S1p)-w%)#5Q01c0|0Pjg@h|Oz&P<};!bS~W4>e# zTYPO|2$0|y#FOy8P5lV*6}{Xq6wX3mcgDMr3!?%__%dWro9FY+9ecAWu`CP~A~yhI zByq$|F`g2DlyJjLI9o9WBcop6gCV#x9uG?Z34!4PY?c7;u^-tMj0ec|2m( z6LMq4ahOn-8-wp#{tWB@q`^aBVVEP4>w<*A;BmzJKd}e_C50hMu!}9|JRS~t$ZcSQ zUM#S{DaL*OlU*~o`s0(wMDf)L*?aVD;VedtLZ_JBI*)FBK7HuMC*?nYr45}*i1 ztjG@?2UH5mjQC1!xWv~o^RWg+1RC%TWAoL?FrERk0S*HM1DF@hJP%Mu4h$Wk7tT<~ zNvBbSERUio=q&;*Bi>249eFcQ8sf{xL8S=~{N=%+36E8crWl5}spW-JA0x09k65m2 zdB~0kwgPOCDRgoetU#tP9KxUr{lv0;P78Eb7&1X}0kSEWCv=J+@Li9O9D(J{cx*8r zqTC2i9Rxxl2zUjiVjE=U#V{&|i8mw8%!bh-NM;mt-sD}Gg+7d6B$>h3W`Ri)!WYg@ zc_#(zo(obBW;P7{m}0*CoOmuDh67413PTvTJrBC#j7PgNN(xq#d<8VE(p5}Y5~Ws| zuw`~hS)LJ=A{M1pn#U`gGagEsLx*RJIbElGwQyAMHM2QFX|&81muwcVS$Vy<#8pwy zoP|^Jnz8E)GZ?h7SCNce(KIL+S!9gi*Fk#8mo5WaVS3F2Z6lIj#co_$UdBS8%FVFP z!aNBU>4Ii)39P`Q(Z+L+l`y*a%X%8GUPr9JamKua&C4t&o4A;R1PKPBqPf4w;sr|B z0v;j-19-~?3zua^Ry>52@DHMKzP1@*vofm~3qSz0OkQ6WsK~N-nJyL;Si@o(ETVY= zjDiufoD}mgVF>zRO4u?e(;#~lgXQFmpsZX)t1599Y@YecBws|Kjn=QC&`FC72JL__ zn#{}Bc~N>!%vgn}U$TrYLblAKIgWyiWzfs3%RFLBXAu-|9xt0PJ^^a7%1qvBCJ|^fXdHT%&&a5z=;p0?-f_9ZX4$Mt=V^q) z#gZjO3gjWM20ISmq0eaQQMk(DB=g8Rf*MJjlBm2|%!@S5z02h#12agkP>$m4dYNQ- zL9#4cR7uS6t1M&C!B;a7Ryl|IIZ1Kq!NAHAFUPBxAt0~_Bfr2Iw9P0WvRwvhD49?2 zD$663Me(A1m4mq@jJaePv-u2DP{x#9u1Xl_oPwbOEg6Upe((f21Ehc}T;j}GC9eZe zPvI1Cm|wEY$y0C2>?K>|ES=NqIg3jeEQ^ANO){6I@ghjWl6ml>#7*E+Z=O_f90a5SM&hDO z7l7_MD!pI{zo|fgvn3c(K3~8HLN+xB9?(t3fqIn-KCqBsw1&UlA z{0@rZQSed8$|zsW(K4sdp%Ay`b%tQv&IxA3&QX@fxt%OoWS3<5uml5{LdWn_`Kg01Ri*XKp zhs9u4xMV0UNuGg;%rU!IvRQ!Gg0irJA06H`kO(6c&2Yie5IV=4|BMd{>iIY=mN2YO z5q~s*p=Ts3gS@mO7DDZ0d08;f%~h7BN$E1o;zgG7LFekyiDwHqtP4^kJc^&CWVP}U zaOVarpO$GHBxTONjWTbMX2B&-I#I?6TY)w}>KxW8ORf>)gTNe&ibwW?WzsU8$7v2t z?<4O2%liA@{QQ4dd?w<4NvkD~$hN9^c^70|q&y;=hhoDAO{>bw@3Jz)PK9_d_yWd< zx1rp#%7X*i9L*gblJ4Baz*loRy$eTQ-o@t^QAK$E1LVP|+aw=Io8bQ25OkW}#nv~$ z<8vNxKIMr9!uf5`IBD_{6v=JO_ib=IJR>qUu57px!pG%d>1C5U0%&sPq*_KLJSIuC zumMYO7fTOx<%m{A`ZgrK0O$^UFlp$Y(|K|m;!c)#Vf}M1kBD>Xb4mb1N~68-}H|Zo|pzJma##=P*ZKZplp4Z4NpTUJi<+?dEzZK@~`UM2^+;i7} zpjj3BsF8Yl3&Y{ZB(H8wCH1Gbw7yGZ!n2Uv^@XJAP8lH0G1#2r+{z%lMaNTWRGgCP zZ7PpDUir14itZ@m&_JBtqCt6okwft+k24M(h`g7er9!wN7+zxT@|6S}UHJ~6#}($? zFL}YY>L}l>CW!-ntDyy6m+z91pnK&t*Acoi!1C65p|>{7HFN}3W8@y@d_whdnq&8l zv5ceP65ve3FIfsmy=F0s<0h12fnlLSc|#-0?genC!aS{LgEsZ_{h%L^4JI#R z@+(>-MJY6Sgn6bEdpEX6o6&gV9>(?Fz2WObYJ2N$M*H!0ci0|w+wsNbrdhKxacg_O zA0Bpx&2Y3GZf!FY9`^-HdlP^SrrvKh_8uy%>)PfkbPj|4 zdcu>~OzO>M19#!eK5#VS$<26Z*PHcdFy7kZoqe-A+@^rpi~;m`&lAAdK-_r4vm77l z9bdaLJPhmgcDuP4jn|`_zn%EmpUVF~%cpVAcadpf?9Tj;!sEOz#h874B-#T}q9268 zIbQ7Dqx&>X%7aasx<6WKlg|adezrWw_!r4~0Nux7hqFdz!CUxld@se1fh?D#9qsKvg9NO~Tj~A)< zJEuQ+_0YvHlJx+OA78qSG5hX=$iBPW#UCR5La^UMl7A$q?Q5cR`18J}c3P4tOWmX; z9mTr%tB$G;<+h=;dcCKHs*fV>* zBUwLHm0auS!mQVk7P{K%h;361bk#OG&karB!4I-JP!w_0e{z1*lXaaZl{FMyeX6$y z-4jJ_pK7w&(Ig3ekSGeEm5jb38-gsfWI>b1EmjEv2jXgq|dsVqZNow3gYHC(^n4$3Rj?R@xm9lMqeDM{3l4-Zjszi1rX@5cASkBQ))?LLvG7`xuu`< zZUk)g~?Rg@G>RgOhb(~k|gb1WW7!l|Mwrm1LMT^BXY zc+zg!r+uZZp7ousBI=5GDuN1lM2m1PD@W>)B>m<0za$aQz#Adt%^YhMMp1+V%Jaw) zz1i z5T8NyF%J3Ep>G4%z>LE|IfUnh33-kdH$p%Qws;Z}xI%qs-(V__)$Rc427X*dEV6bTssQw8ORwU5_x1w;wTIepW=0A1kn&%JTAcH zIZ}Xn$^{!tV?LW^kr@pm$0amyNNk}Pv^2v!&2NP147k9AxICKcSHOm}o1H5IH66O^lOGub_akh>byq_?h<7Qs4Ib)!K zhyW2mQ2Wc6&aWbhU6y(UPm)WjC@EeQGe7Zhp0J2`A;L+(()ndsA~v15jKW1m=V_FZ z)Jy1Mmc3!5TKm;}&Rno0^m@t4P0koYi_0a+UROaduUO9W92dEtlANx%i#&|kYsPX` zfkrKsMIM767Ys~~PnwmhoYfig*}R}d!7_y4MLB}kHwLd+(Pf+=7Oz+xdLFC7IJ(9q zw@#L#9I+AwIbAMEa-Hx@I~7ly>nAI)N0ue5x&)|6F^$}CjclBRjvX(8yd-?yr@)u# zB88ro%>6WR0ZTB?Dq8S_$3RV17Jf9#5T;?pu9pQ4=O~=h7zkVxD84GgOTuEX@@f^a zkgb!PZCK{h)hwxM?x5v~h7e1pIZF%Z3yZSK;%k;?E6-l9K&Lqa-BK2kEX48RZ3^B0 z?bY|c`T4)BKc5^0Uat{uV60~2n}s8yAI5_~r7|9*`oXbGQWK zoUq=*TmNKxxM;GTG)Yf}!_9ESlZ+giy_ohl7vs%s))U*l*{z4$O?|T;jt}m7bXeOw z>%`_}U+*WA(P*+cY!73bZ^bmZ84q@QdpovwBc5vHVzT2oDR$fS)*Y<(o6*kRZ8p2@ zU~LZ$!|j$kGTeGR*t1H?C zx`*4mBm3=sxY^&>eA}h{XtW*fZ#MhQ&2D!y+K&deyDtqkw#~PXI@F^v-+O61g4ze3 z=A<57j5d?O%>n4Jfft~9FuXY2Oa{Z6XABweG`=7qAZ|1stlh(A2O#Zw-DD5mZExzs zx*pUQn|ikyG>V zp#R2cG~~J%O!gahySvRBd@}-SFShQm9;`R}HP0Me5675AFret24QQ``nkcuebJixUsi3Pku7kZzmg`3}^(_HGBN-hhtl(H3m-usd8_Y=Pd}jlK^1Az1X}Vgxz_OJDEzE?6!1?g6(h zh~FLXEXp9#L8HI*xaM1x?GE;2JZ_}C1sdHwbdGV&xj2l$(CYeTV*l+pZhk61m7mH_ z<)`vf`TtJ&bUGoJxxp9b4L&Rnt-<#mtMJthf9KH??=wK&IoV_XUA2euh`i^Qe>fG# zBlth-V|O1)4>0@sxrqm{d(Hzm9~Z&n(=Q()@*V~#&`?o(_Zj{&^hnlb|0?y zb>ex~_JM>;zvG6N&OL}nQU$%u)$=&>pS4^2;mZ$Awawx?_4uEG>%CvUIk`-2a{S8vS5`@gs1LllERhg!kqE-`4-`!_IQPr##jnq@ z@St?+R}TPqa8mYh7!Oo>h}54o8DSoq+kN$JvbN#r&6@_mcek?s0^YBmKL4>d?ERYZ z>hs$K|L&9U@1*kTbf9~k7cQ&8swZh2zeV*)s)AZngf-e=WCUNs)~+Lmn$iyM1bFZC%qQ>WR`9#e=WQ z7xw9ilqqt{>WUrfH)B;CCYp5Ob%k+P7Ievf{ii2qvdj~{=<+k^*|)8UBn{M-p_@v( zCm;W(*S~x&3K!>+PKT$1VZZl{sdc(Szjt)v+bz8%D`!T_Hq?H9*fE6q%oMw-sL6lw zR0#gXKk2mwTE|rMVAMUblo!wcLO2?k?PC!MlA&}|AiX`-iE?C!N7kfch-D&6=O7_x z5G$jh3N*=2;Y$;=^L|?puSi$rNl)y#(DJr5YD6Qk?XU6iS4ESVOel@LPCgSj= zmOB5jz-(Bu?N=qR1PGN-9R?M>MmM5_lBf)HQ`BL(6x?k zcAj=yXBWrkiYUPaRn~-_+2<)oz}Q;qljKZA(CR z*8*^A%1>mq)zRekk=c?un%W)pRj8wh(vcy^9Z{BqQ@E@Oa(i)MDxz}igB~SQI#RkV zpr@_KLsb)6>Zof9T}9HgzI`h7<<^m@3_3kytc#MObmi{kC{{Ik^jsfxHSPSH#MC^m zB@Lfx`qQ3J3FmF)o1Q9&iaCCv3X0kRgYeFeJ!;DRv0O+UW2D&Kp?D;BTGnx2Fu(u? zN9wUD&4so+Q#->Gd04j8i_S>;yOL=Lrb&eJ^QYZrOLJLoiK@_1dwP1TwNyzkI=XD= zhGI&VV6-|f`X-S1d@$Btwj_P3o`|M)q7J0$>{K}K_Y6sBb;Pc6(Q9{=jwZa`jAcca z&m^IzD&k1a`>H(bDyH5$Q%`$?a_hM$3M)l;2BXATF*;F2 z{YV#E-R{v?IMEE#Fl4d){6!{9!?tM-1$E-cJ$Z6*T6Kk|-JW)I1Otw0%717`8ko=# z*t-rRoYZM`bWwZ`Ms%gAzwH?<1Jr!N2glY)ThT`5`S;)dwf@Qwx-;QeRXRpX23TtU zDbmiLbdJ?m|NXflL{iuPdn0|)lB6C~>Pb({BN#`eXR0ZI$sY|*l$J0O!Bqbj6BHtt zx+HZCurj4hWvo1tl+icx6WVGSF4*E&b2>fY?8Qr^){8C=u~S~=rV<)LPrA_O%HU`; zQ8c4H6ivx^`ddjBdX_NIw2o|;vMGYd`Bw7sNPnproska1!${ZlzOAI@N^Q$0dbfKl zom`GyE6>J~rfBMk+SdgAOc6q5D4wXjm+fOvpP&uo;aUV^Fjf7;JU0zZ(N!L(*ON@W zudPJ6-xf7V9Zm%pOC(KFcnToXJX1u&Fpf$=1$miZ3c4XF+EdGI_tlr`P?VopFcy2Q zR(Ak{Q~O92ThMYh_?e&`3#rtR+t1qPx?r~3p3>{-J@thssz>G&b!DYxE?O^)0ER$$ zzZZt43&wdbHc1|ex!+i`TZ}kYfbrf=zc(O9C?Ws@ze?tj-qB4c%COAL=n&6KzyFV z#B=yQQ=#vLGaB-|C=SB5Wg#Dju^sWP?L9h;JRCbdwwn#d_`-flBG+#ck??c@P7*^+ zVj*Gyx`1!(j%f%a(8R?FAdG_`3L=k(qG9-im?s$FF>J0&5a0W1M%`)bMZ~rU;b|!> z&-Ma0KsJdYIHWPp^AS@Xx;1T*hQP-U;~1eRz&>#zhtOF7Re~svY`!0s7g^H)P3@4{ zP&o=nlS;&jJ&FlJu^-U}WH{sdbR_`UX|~p)7~2S0F2U{$5gc+%kj;WuXvArM7`z1RVkh-+cb$5ykQJWmV4so~pu@x&U0 zXK*2W=dl9frtbF93B)!kr#({O!?OH3C3=WLCgg3dcf5z0xerSkqAwYg>45l z*&u*Mk6?!)AB5mL6lCUO#|i?+vRpq1u;(~oXgR*`&Vn!?_RMmpQ)_D3mgk0C=Ft=p z5`{kXJOtXoAr8Z4zqgcp6z2(9WX(d3uYG+-9u-xmhuy z0VY8hCVU5Xu)o=i5M+bYlMqM-LamTTFD7B+@jcmi1_@{z#8$u~^a9VO@ia+zS`qG$ znbHXCm&8+I@hm+Kv~+{1gFtqO=jjPT6!P2`kqy%0R3tVSq?ds8$9y|IkfMj&(2JY> z(-P{&vE^F``&^4w#G^TRmJ*EO03iosF970vC-i5S0<+Wx$|#S{jCmfRW*a^l#M}Vk z7Ke!=xCAO>?80#HA(xSyZ+G>O34BRT~;3Ahw((4A%ZVZigCSPt(b z1k8R4-!={@=E*h!%xwS+3HgZc5*UM2Nr3#==E;p{IP;)S@sustf`0BsJlP3P@Iw<4 z`=N`Q#7M{o^-wFer##sb;T9Hy?qb4C5=9}mJ)U`nLiY|pNmDS1*!8@ar+Psls5ERc zEy4NJ^hsMCLxO-X zpYqKBL8y^S8qE>D10Hsrn8)e{5sU>;!3&^%63r4&2hWuh+kOZ`3$Kns9vK>Q;Q*X? z=7u~%l?09bgVex!K?~EsaYO3yAq9nw55pPolF)$6_*jT$t{*j-Mk2o19?z;2Cce+d z35upMz=-(9ebE0vAs+JV2=PojKtJUXuOKeI8y}5*%L6-zW838e=?n%*2giUU!5$Y# zJOyF%h+Q1|Ktqf$^+*8MK$ITO5`=k5tOSq{o9~E7rvy|RMNtS{!QuNFlEeo)jBT6n zOil5$nL|OL*T@|H2cbiJmyh#c`4kuc3*zCnIQEglHLJPR_L9sB_Sp>|Pr>z0ef-XR^(6!;o5^@XYGL3^N-@GxJ zMQ+Tamnk1?n|&1#w^ZT+t#ASlF6c+oAdYw#ZyvFt;OqBs4n68BD^azy^Qa8?g8hIM z@qE5q&Y>hB^V5|_SXc(H^2MS^GZ_9@z!Jn5TV!ZevvR)5$uwixg8E^!U_KzPnLmeK zcnMvWU1si_Aint^Szyf9^T%br;A_;c77?0SHD$|Wl|&iNQWh;TpK$9<=(Nm9lFk+( zVI-~c?3(dC0ZGntODyO`$XLqQs&F$#N}RJK$9Y7q@_Ej)2>4lrbDR)+wJ1|sX0+gG z2LSzLG0!3xc^I^sM*t)a7!TvkUgsq$X|i?;wn(muE9_-SmQpfbRg@JjejO&^B~V2& zg6DahW-L!5=8?+?9(+lK6Zlz?76~qSt{g&_%wN`(LrRusm-Z4y^fI z6O>mA52ta;!aB>Z;{<4`!;G+mrgIjhX@bg2AE-?VoaH>jLP~)e5|l*{&OyH*ipVcP zQ9MMNO~WgS7v;BAIiK4gFc?*rMUv-;t@9{ZBqI^yGa&+B`(2qmrLk;K&8jP(sN2!!MAX{OiL2vxi=4k#Lv=KWs*f~5%BaAV3s^Z z2H6%X5X&kA<>VeK2z}#&{8(D&G>aBjIjK@m-hwRY6|3SRxdzB6X0*;d5K|7;vB~C? zr+Y~mT~`j6>nj-j;m*WbCReWBR&Cc>ja0uu7}6+T=K9 zs})LF>N1yIMxaKgWVECQh&{oS0r7pSYBO6&Wc3^ox|7$Dv6RMr5W%WXTV*txCWucD@Nf5X}(Gl z7S0Q{x?C-aWnuH2MsZnQ&KZ043bFiEmPXZ8vAPBoF_d3}{KDlTTVz)iPhf;Vl&o3; zh464*#0xM9zoaY=S(+7#ih4zoq6NszpD&>+(0DQD>0GMFrzOMwWs>HXXub%G$SP0~ zT`$=z%U@kG5GMB6ie)7&;aQeb20w;akj+6A3(N!k zj360r4|k6@gPBPddz-7(%#Lwd#t9lzdhn?uIBpGx!H#7GLMtouRnSe7NfjLOP6dJ?A48llc9M+HE zHl1;}BJeXm4B!Oh2T2|=dx88UxL#d2=qILw6dGT{IU-9effPb;+7RX9bwsi_EMgCi z;XH&17H~9qN$kfgyW>6;rAU1dtns|zFAN{95*J(kn>qYulX!~NS4D9P7w#FH!eU-k9i{k0{T|LxB1}>mf1QdI&tR5#eg~@I z*)?Mo?+Tn~Y`@Be@CnZ;*n^Ysnig4_rUA14ET9P}J-dbFTSjvyjmyA=MGIGtLC~$tffeC&|JWYY{nxn8SG_163J#A>ywoPpKCXTubB@ z4rg#qh!^~R4wv%tAiN8yFky7K4)xRgE+{kjk?|NWdLa*OL^VQ2HeP45dh zzo+5X8Bc;G%*Uc)CYr;l=WtAdy+syhBn~5*h$4bRH1wP#VKJH3dB!%lg`tG;C zY_C6+q!3nQ1M~7&f0I@pLwx&4I#D7A$1%GgbjtidA&^wnKud;k@W=)*IVBgARSef#u0#3d!WS5~^~zlCSs!~;g@^s84$VpSpX?C0& z8|gd_QyD*&(GAdRtm@}flp0l%P6*1+E0rr9>=OwH-1{7jWmRRZ~; z60>`lr4wn@<92c~67ZzeR9F7blXUL-)j)X~fsn`ao{I3OS{wXLcF`L$AowMy6hd8T zT$)jp>NPukjoDiVP9ra;CyJ)(__b0C#ZKLMrEF1+R(ZL2TnLq`xO4KocRXnE`@^{# z)=!cqc+A?!`En@Ne46gcD^m)SH8(4bV(2+P%podW9qLZytJnjRgOeR)TE4{|Rc%PZ zRhBuI}!D~_2tipvk?M^SX5B!ZXOywcSw9c27|#0Gld45_1f(B_weUtV=nir-Eg;CE?4V5DD$u%Z^x!NFwND*T2=*>Zyro@ zGgxkKKnc?t4*T0ePi@ohy&SgLJJGDOxBkAry|w=nq0FBharm~3+1oMb?+gDSnIDUXe^V;Z zImBy!RN(Z~@VzG1JD)$gof=x76@LDqp6?I-btZQqMM z`sSP0A87Nj5T>_+bv_Yp_wl&Lceb~O!GNB3>c@So>4!yqIwA>cS$*@#AlLUp!oGRu z^#>yiAFG9Zad_nWF8iB>b3FzFzOm<3)QZVhU$gh(i>`Blhh}=q$paWcHTd0HEYk#+p;XR z>b>lFyWW;mNjcYgs;bD6B&&*g-qeQuehX{NG*$Jw)fni_UhQc^>8l#-sf}ub=DGHw zu1HPovhz}rp2En_n&&tAu-=h6=Z!|^s#k9qlCJ1#M@ibXhGo7ODXoFjRGLoH?w;uw zve1ShRju_z9!uSJ{Yn~6yKZAt>uI_t)ikxMo+)ax{;Q7u7xA#64+ow9=Ktfr{7+A1 zLyqclzuUD8s%Y02>SeR>q^`1>`fOO%YXiM|e$`bPujFQ`f+ zrW$pbw!6xOq_?LnwI$c3vkS1huGO$o)mf*lb$aqp9d#Q$r6qNrN^(cj)XUmaRqjY_ zvsJ5KOLe_tfVVYWyS(V>_46j!pbQ(*^JnVls(z))`gyB;b9wiNqpJ%=mCw{}y)HeO zUQ18p`pc2jY{>Ojs#Jg7Zq}NTq&H{U3*}6@ZU)_9qDr^@hN{#CM8${-O>=Y*sB~4S zqxTyPU7AX&cBQLkxBjx*YIfA7uEJ!gntI)7*IUZjdHs3o`metGQ-e{$L)T@@G_j-# zommDm@gXL6v2F;b+{9Wl7|noBc{npDGPY31L+%hKbb`=u33c%ap)tXy%MLY>g2uFh z!1u9SNr;aKDK(ID+98~~SX3f}fo%s1MR+8fG6x?+Q^z!1hO{*VbO@<|1t?$u%0b6~ zFv4wvg`N>w)&w*rprOaSz;!t%Qyy}U299r0Vi=w`u^Hv~Slgn3Z{RaB!a|#xSbfIB zsv7X6M||et16-^nL)auR0)`bQEW=0P_%xb$VO1DmMyJ)&T!xP;y%3+$89_j7&%~e! zd>jmhQ4DtoW+t6+8`Ce)o!~gmxZ{}M-vA>NW(Em}W0T3mqch3_&kbE?h7XrP2zZwG zE|ywgHcZ0Am{1o6GB8>p41MDG?j$%S=20*JpWB(t3Vnt?!^$w+2^kiQaKN#%SvWPY zkWN6cfCR^<${|jy&q=_+5@O(UVi*XYJqOhEknlY4@NskX5YQwZKFtjSEEZ!kn3%u? z0e%q9ToSu!VOBEk^2ad?1TsK zB68s^68~NVi$xmcRCsyQ%Aob>c^13S+^FO4!#To#S(!c_G9iS-{RL7ex`l*VDuc z6PMF)72$JdfviGeiI0WSdmg8DhII2H%M+|J<0m`|MH+*wxmc$(3fMf(k{n5R>@-Yb z5#UoB5G(EimfuE66omI>z=9;3`;*8PZo~`9L3&1<%uX3k5?6eE4|)-YOk-G8BKARv zLbh| zk+Lb_#Pw5Hh~SshGutMiDF>Cn|Uv-->jZ79zrfM4%6e$Z==_QmoKl|>tzr6dSPayBcBO#AD@ey5fDlY2-l02^D26S2d>9n-ux9PyMT}8B+OXX@z*_L0tM~0bk@t zJxaSGZZ6}XOeP2X$_nB~v}}IDlPXf?xKc8KVe<4qMx0kL?~zFSNcLUre+$YwSb?yO zSrHo}vVQ^~(?fF^S6M3ygz&dgu?DxwF$E z2uk+TLt8n`f5XB!3Z>11xnGY~yXB2p(Z39q`;}F(zw~d`eRI6q@Auo~YP}!t2IJwz z+-#AuX8f=n4o3rMg%mK`9a7B&?w@x88tEYYnX*hU2lh9WDp!^{)T0w)W=kW;EW9 zSEHNdX1nU|x2r9Z!7MkM4Gi30gX*wje`Ad*DwxsDaKB%!`rF-&xqBFytKGwJw7FUC zm;E&YZ`|S4LO-VtoQq* z)j$8BcYahB?YBRz@!v~l{fq%WofrH)VUN&Ot@{t^%H^5TIcrFY+~_JjN!S0rWWlwK zsz`FJ_5|8Uvigr|+GYDvQzS+EO49$pkd&6v>Nce7ZmZU7f7QT(*3hgbUn#O&>Z)3= zua%zCdfps0yRxFTumZPImwNxXVO~mYMXNO$&(4+l4CI`v&GU0@s6TDI`dL%fpI`K9 zt-qGFnyO1vF4j9qHd}Q`>ZqE2 z*1c>iQeDxt^Uos?dac%Zp@YmbSLt^Z{ajL| zKpl2l3iN4q)rL&lXFt;lP1ovErKKu=c_vHrSxq}T|BcpaoL@GYV@bR2Nu8P^J6AJ_ z*IEtzX>;7v!56g~<<+3^tT&kGn%o&gjk95I*wbX?f7WGHyZkfdqBT8lNV43~YW;Jq z-Wv?-ZAnw>a-(*sUdXpvBh{2yr!9d|J@rbuQYBfxsa-jkKdEZJu6NC^dIQk*ymPO1 z^o}lf>$kz5T*+$hrg5S7ySl9E4MnOc>Xq6A?_Bqv>Ss@+dP}{iX*Ee{zIt{kowuIA zR8OTwOH+EyiwjA)yHuNJdJUF?tm`nc(d+aSrLD9Za_vI>H-o22O=(_U%C&}ce%YyM z-D^df)S8$!*X}lyPQBaAwYEIE>NL;P#^~jxtPg+ohtglc&nm@2zr?KS{!%PrIrSzL zEixgYV^YlMz^b;?^kJuKyDps>hUAcc4<>PYn=5m>UMB?FI3+Jo`TjKL)d2y z=xn%fr|&u@V=z4~Xk&VQ==zR7!%7w~kYh~A#GzBf?l|W*^9=ZP#zMK2aSTxRF`>yu zt+4#9?|~R=%D910VSqvEj1$|oLGjRrT@xgpCN|{;8s=2l5i=hvHqa_|-T-g-0fRYZ zE)0$71{RoUV_plZsFJI?$P=Wl#wygHgl|)yO%Bl3`d08{z7lbnyTV&}nd`@5k}y77 z%%~9ee9q~8@O6Z65fgJlL~%z&R;1*99`W0h3s0ojJIKSt7krVDFcU5oV7#9*;jkbR zX%Px8{Mcoy)Q{|h1v$5Zk_0Rc?^#qtG>=o}BpA}X2ty*U3r|SI?w6!AF+{bzjbcaK zav|&tWbjD%%R&TV<%<>cit_j-n2OsOw=F>?7V#6|2x4Ps`Td*=c9&u7kI16f_X80v ziX~fcaGMZ@C77T*%~&WFIhm!mSgbPk;v%~XSdx)cOg+I^6o*M9GRvXG0wzI_Bv_^b z51C2y8eAh{;oXsiAaFq3VWrS8N=3BFs8O^PSe~6 z!&0YWS$qEhA5JB6RRd2-alI+i;N zDV9*oP-izS`6*Z`oFh5+V;HQ@@_W zlRZ7ccVSf=YfBxv16~ z1QNHn3hO$E&B__Zkeb-$kxm?EeqI%1ocKqu)2=$?k1*I_cL<9Zy;#-#v(pNJdn^37 ztOB(v{0(P6&#M7T;^eOTe$>`~_yDx^=bsO4u`o{4-@u7COC)o*-;b=(a@Bu8?&_JiGMwI7XE%l>d+F8AxfA!f_k?6%9jxmi|a#I^%#Io@oR`~BF$N@C{2 z@MiNcHa9Ey_Tdz@wO;NA>m^2Q4Yr&9_-44>ESKhPJv4{?(Ryia5ndbaM(h3xi;0a! z!|iJGaI+h1Hpm7&FbC_0orQeRW<}Gy+Kj4dVmIr}asb+5xRyCy?ne(;TMUL=Z7^DE zJzB1-V6BG-bKT!E)uL7*_5=9?qnq03bYDd;IO}bVaJ*nG}RpseLP1E6OTa%ymTbis(a$RZE z&NNvYxgAZFW#vhybv>M&OLcYd{9I{Cnj$rj*$UpvT33~oakEjE+V$3@bpGT_?yE|( z_vFH^tLl{`H$bqiHC08|&Xm5cN=i$sY07iGZZ!0PiVRy59c1V_qH49X#+9m#E=K42 zNIi$KL6+JYH9D50NSda$RIMxNa#!t0=WSiOlIjhmQHRl0ts{LU_gY;^Y07Q&y!pJ- z?#jqC(`cUebhXzw>nojZ`$?nYHiwejZa-D6E4{-TGo?S!YwbUMsV^IYi*~4V^rr)< z;Wd>@iS|0zEwDIib{fsDa@`#a2QRvfc1`a~b-9mxN9S5xKUccCT2pHJs|FY`&@Xym zO#Q_Tv{5DL9F!ikn$wnkt-MrQirfOnDA!U=1y^VWb2|S}mzJj5_kA)NA(Yofq9}6~1_S-BixCGkx0C zn^)44$&+qVYSy3D+`)CN^|E^*>usggnJF-@(wWxQp6Io6PwBRvX{{E0)_u|kjnu(Y zs$GIHFim|}GIjM#Z|UkqT{6Lt3++sjYf|leph-35>>MtEr56oJIz!%=5OYL*56L=^ z+XBvUlaM1_?At4pO|5YmBc9g1ez{bFvGHEI2H|&umJ2QhCwGrKztrB!$!&ij7p-!JRog> zhfznMs~<9oRwK^@yki)Ng%mtsCPrDIWg+GY8_v}8EaqAv2&Q%g>0uo@GeCkA@GOQ# zA;}64CzOMuU2uK~BYRw;jt6)XerWZ5~Vby zcP4y=VRb@SM1a;wISa;U$HL;B_kEFkA3RCT4aLq#|9!IVo2#zm7f27t7criAZ=ru&A2j1?7F_ zMIv$GAi5VtLPQvefaX+0bBCsO;t9lh3V2Cx)1u^QT4agH;~<=4w3bNncpkvFtPJDK z75` zR0@p6%cB+e2ZOt~C&D=Lm_MP*FfQQu3o#d42r`5511gB+dRQ_pq6?VsfX+!F=1G7I zHJI_4f(yYx;OjEVz~nF%i$UGH-4-u)cAG4Ut z^azbOhY#gJL>eD~i&Lf|Ev+O>vFR~s@2C(hPMMZLSx{QW2rap8l_pnah@p@}xwwQ> zTEPqEYR8XZPu9^cN-70Gx!iLq@THRbCVR3%kZ@xMP!8+O1#hx9j}Y6Ty$#yCyxQXt z7$j#E8s_F@0G*@hp&mSfN%=9w6IF^3=SeFy!!qUNTU!<9R8Aw)F5kqC*^XVh#X+@7 zNR>r+aAL&Dq{_UtqpDndadcYsw;B)S+flWLRdHaxA4XLk<)nhGP6@1m<5aVQBNxt5 zybUkuo9xh&4k#6LI#%F26vsQJf+vhtuoEkDa#{u*ez;rito3@2<;4(iS}z~WWq*ayN#@YpjvfXWO;r_c8*c{VwK?jW%ZKH7 z|FF9mZ4Z^(_WRLhGk&-k4OT1Yv)_(}8*{h58TB7V=FNID9u3X$YHtldo@Flg51Zk7 zJ6u(jwM=s}-t^bwaWV?SbEpz;^ACA_8&2~B3-E7BIbuDwf+wY;_ zeh-rNH=DtJ3oiq6zZ;CK73jDFTQ-~FZo3(6mP7b6+^-(?)^<4@?)t-W zzvJx_aFxYQrP|*HHEia*kAHkF!ZP{%960My@JA4p@1a8PmYDz4HnTnmG<~Sd${Rdw z`hjmhce6g(=Zob1B=Kb5&-HZPDMMsWA4`LH$6eF68#pf3L3(uI?89^a!BQ+Aoyo_h z@1j`;7W;R@gq9!5ZTnnQ>f6u9q283Y_yo!Rhd=y~CV@)}_|9E@_U_sZEqor&Uv%FI$1qRHS-e zR$i#}Uj3r}Y^1s4vw^O6>UF6mH@jz&E_GGy-+k4pb=9+;tZ7%e-fn6m{aIVPcvVw6 zQn&xAr>n}ZrB-Js_g?&WttCyGx}-MG0{wYiQ(BUGqbSOgOmALm7cIG^UFw&{KOMu! zirkkwiY_-m$5*35KdWo7?@Xflhxuh!1f2)Hn^>*KsT2IcJL+#ZIw;qf;HKmCR=fBpZmfuz{6-9a` zJsIkCMGFl5>Yuc4bm^&b<9KIZHSG(nuV1Sj7(|tNyf$uK)PJK4dDQ!o``M^tHl)jjcBQ;jXDw;^RIYVKVAJ0lUJhmD>Pk`1TP;QH49uFO_8KafBXw#m zMV9Nsx}rRjui6c%-@BA#z16#xJ1}{&t2f7fPj3vGf1qm33+*cn*}g&H>*vpvXrwoT zS88o-UF$V<^GcI`lR96$s>?6iT~nX8$m=KL`l$YAciyj*q1ykmU;OF6j_PNss!2~T z+S+;V;-!~e|NCb5D@}f;w3?%KyQZkkw!Z3~E6+y#?s;8$Db>{8b-gVOmBvVE4!ZhP zS8B9ta`$F3SP1qN&(nI=OPTWPGD2p!2~|rwx)!T5ZP%tGo8@08K=_;4-hiL$f7U|{aH8*%y1eY zx2a2~6?-M7KC*xth=Xy9VMq`R0mB&{ac7o^7@1S0JbL)!5F#rqGH?dOu&4p=4H|@A zXa|S`F_#mJbPAp6%nm`hfcimTAe%1|&%zM!wQqQC;KINzGp6tj{5aE@;e=t}Bi$~+ zyt9yCtlET592f(J;-TRi3`T-G%aBYwq(5dM*lqY2$K=8g9!Ns~tYV}^l#BaFZ|Maz zupHM9(LOuCF_27l>QhEM#Hkzy89T!nxYO`w7{3-;+@u6~P4VJo<{Ng1+|HgwKsjnm zjKB|P;gn!(824P?Ln2_r*%&hNA`vV`+Ia>C$D%{YgoP}yLerR*%p4RhkTHu0tw{6CqQ{?xRsiSH2Kgh|1O zyMP)7cPheM=7Apw#&&UVkbw--JVe@Qq|ElAg$o|UlvWJS^C_7a7D4iBe}Z@(MW}3^ z2$AzF_wFMRiqaFYAZcFAky4N#I$~#Buo)6#B737RD9`R95zGadMuqSNB0B}#&+|F5 zh~8xg0;L7Zr+x|jeDPYKQq#pktnI|7eoRx}Wx{ny5{QJbG-ff)b0H$`-f?kH^T^{g z2t=HPQ@;>)9*MX}Qz{4-ceW6uGQ6;bXU8lJ#l6UaOw58rB=fikBO+qE;0`P+FToFU z0SfUFZg`QdFeiy9Lm}=M%V3W4IpHatlEP+WDv~U|6QOSlZi%^ItOWI3M5`s6 zn>G;=a z?|~(4;*$evhLK=Z)?)R^I?~u7?t|!7=*342rrPG1tXBnxfspwjSY3Eheq4o7n`1bnd5v;vwi#B4gP z_9hh;^_Y@pAzfQkaT1nO3uNU-r0LiKalD{7Kxkg+WdUML@M)GFiM)=Xb2tn=xEu9x zFjg!o4*^nBKR`;xxnE5MoT$MRuZ)ifm{mUJn1T(H_;GAn{exB>KcHPRc4R3;oxle4 zokJ!i!%hhhQA1z0#o6W<1yBqh1!}Z7xxd+M_S=nhv##R22BYN=nY_m1 z{dzez9|oJjV6@&X_nZFmM9fv;c7sj7Z()qrcx0|CVy@xN?2p!Ff4E)4yUk`jUaptR z{%ZNK9j?qR#(1swgPmz^M$6637Gux056k{$wSHJH*XtFk(}%s*a=+ZJsu-`ec{4Oe z%fWE4Tpc*M*30b(1|C8KP`jS*4o17(erax(!~Sly-|yC#irF77cMl+V zwFC`@zvtol{r2OxFXPpko&b)IBO0G2fxRW?3%X4|Kt}arwjYL)epvd4WxUx-Bzt+dnxvpL6s?@7#$}21=RqLCwT+KX!0O}(#a=Vyvqt3Op6 z!)K}@*Zd1hQd-03BSpScBy}V`Z;YO_&dxPmX%Q+ZtLI(mtgj3tRk~J{7yYyPnO490 zN^h$*kSd*nA7tgcF*MGUr&^y4b*VL!o_wXh)Seoxt~8iTrRM*W8fQwc2ZPs}XXnj! zO}S8>slCAqRa0d3NpGZl)onF2x${I*8lAJJI*3*D3+>r6y)M6~_3LU&*M6?(bxD^L zsjWzjrlvL}wbqqd?damET+^F9rKNSewk{7F&5Pc7qjvpLQ(8TY7^^9@cC*{5skOGG zU!8aB5~f>T)`u4_8l8H-IRJUrV{qLVgSC{Jeo-5YB>5Mu?x2PYRL`WSaRuW(J8Rb@ zwWGBz8+BD5m|9c1xt6t?%f>|?v{%*6oVfLoBfR{Dd#`tDCDx0&nNJaj2mBf?rIB%D>TKQ7#G2O$Zk6B^)Ii*n*mu{06m1k?Sd z%s@gUPGPsrLgvf}V+bEm*v+`_Se(pUkU9(f3Bo3>VVT4Wy(+SahAapeWfl@9aR-Bi zkZy`n&zg7!a~a6QP$XhhxD}pBeUM?m?JQyzoO=^83q4{vJ_hYjpAy$W$&L%{3A745 zRIaKU;}8N(88asnpBh-;CBULCKAU;O2q~TU80lpDuJ4)z1F!<$F+0*tQfVZJvAI^(y9cIiNsjG#SKg{WHfXGKR`gnH?W!#osj_Z z=P-s1gR!vUj9FP#X~w7>_*g2)0F_~vJqs;Fr;G|Of;Sj!1^2+V2eV|ez_DlG1A`H) zs>JyWeCFUU&y>L3kKFA}WPTV{F;cdOL_DWKfS^n=7b%0Ab3Y)tDJV}e5}HEz3ClT5 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 py0LEXdtr)C?H>zTSP0h_p&sw7E{ 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

    grBcC#Ws~)}eF9 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

    JZWcTV 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

    S@uQS1l{&U?WOP2pG(#l$Lcv@D%Xv53Od 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∓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Ξi+7KK4;Hrhy)?B)L@mvd?7rVP=(LQ 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�wB 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�_i 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

    9^&wFA?6PRG3*Mb4&F?% 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%0Aj(1c0yGDz== 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%0A1Jl=?$WHJi__c~CKX(BhW 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 literal 0 HcmV?d00001 diff --git a/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.2.subreads.bam.pbi b/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.2.subreads.bam.pbi new file mode 100644 index 0000000000000000000000000000000000000000..9a52ae2c578aa114aa5527e270d5d2fb0757c2eb GIT binary patch literal 4058 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 M00000000000K*GG`Tzg` literal 0 HcmV?d00001 diff --git a/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.3.subreads.bam b/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.3.subreads.bam new file mode 100644 index 0000000000000000000000000000000000000000..2af53d16419c5db243c4b899d850c751b563f8c9 GIT binary patch literal 971423 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ʲyJag!!Ptu^%`ad>Z2@ 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%0D*h%PZ5M~j> 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Ë z>R;!kYXeo1Ju*CELZ-mAypd}<&IrJJ$Ei!$eS0>SG4@9` z5b^8v`ZkL}osyU`&n-v@m=mKe^asiuhnSGYv7oInn7Jm*HF10w6rY`u2J!?`=+q## zr{75G-ZYW|8I%djgXJzXM|hK3n~6BCUnf2S7CN@YlbR%oZRN~ni@}%?-O_7a0`S?j z{hE(x3N%T&=Nq*XFyv<+vjJA*W6AHizs1Bvh!+NlbTZsJ&j9&b^XSCjtrJg3=RuPHCEZw4_BE$7z<*Bw9!0 zw4iyYr*sp$X*vgjn)R5b05PB0^y_*<=X9Qit1>ChvTRbVPd6cZdJ`6O6&9d5unOX| zTqe|6loj2~v)Ble6~NzPbG$f9>1>mxAvI{4Mu5JbpU|YpLQ10?%El+FEL$1OPB)yV z=Zkp0rs;AW6j0E8&X&$28hC6re;MXsktXL6O}v!m)X&2prdc#!ghggi8d@n0s=zDk zdBu!6CQ(R(G^cB}Qbg$~apH7Q0^iWWUm95&r}HH8;xzxtZm7y4pfs+MEUq$|`O9pc z1haXaSn$%gOiQ}j1U9W~x|q`>%<`BLdqo%4Vl}6cM{>FZ5dymQsGm|jr{yvwG@~S> zUKu5mDBt*GnJt)|o;{~w2qZ&v8qK{qErBp6`dZO5N}R;1XqlAk&M+ormJ{ZhPbdYH zpDvSNN|U?_bGn$3#L0?^ou!;bY&oxdnm9`u7a)!6&?KSZY%wp{e`<*r#@Rfkx;IaQ zWq7=yA=`Tvy)aCU*?oRKXaBT=aK#Qr7M3nuq-jde%P?JgRu*Lii5F>nMwf9ghlkjb z?D?#M{)UJ~!8~TWz+9(gv1Hrjvq0u-IqJHZT|^#rSgh!r1#^+km#f^55*EVJEfyvF zB$%cJUFT(&V7M0vDa(`c2XB#!6BdEn${w3sj1feP-@1pg=b_0K>5 zukbHP6FgHC{sJodQmOu1>3kmI?r#Es=f8zt=Eq2e?(V*Wt=|SvKTR>*a^^e?R$blx zL=m@!u;pexgW15iXK|>gik1VWrLm)|9npb^n+=f?@w^FHC5nk z;RWJ;Bvk+nWB)+HAd1kv+(GY3(=WI54GeGf4zw$19Jm^4`g*vo9=8qDatG_fv&*Za z%j?U_>qBj$4eG9eO4E)G*Ovgd4+bE1z-G8<8o25~o5FCQgTg`ozGnag4hGd=v$-CE zyumfd8yucpgSJ7hZW$OJuFtgoM!&w)di^2$F+5ry4sXQ`Hh1a<>sxVy!)yI|Q|bEp zYIrfYxVo$^2KV9yw+#dOWv^}+*z`8gFHkERTtR;0f_c8V(vPmMFRm{xhdm8+4Yc)b zx4^~K=Azfv4)w#0w$|C=`tVNF0GcDN?nMo*HN6kEKh-oi8vN&f8o2fM@%#828BdV^ z=}U0xUrh9J3#H!E-8@JXJmFfot1*9OtsgSsDWT52Irk1uU&P8EasBB2LoOZbF%10* zYOWi%cR%aEvoZiLaTL8e%vaI;7l8TM8@d~|J$~b({$Ou!+B(eV7rXu7yAFc~*$DQP z|6wR*k0yK3i`TE*4*>R0UqVZNxSah7QhHyz|I7W4$6)U9-O?|K$G&ycH*Yigfqw7l zi*7wK@V5QnW>nSV=U&0{e>r{N^49Te<@#^ZUw9_{@nF1Q`19=#_hV~#?RR%z|^5!b;I>hGiOJ6Y%b!fb7Igf2omLr!S(q9pRF#DS4wAGHp4@jq+y_(7-9$GXVlCJRej_$0Jj zDl?Pa+QkYlbEqRV5ijpcJP+LbEXXa?ZVuHpZ;G-Yc3LdFlA<<*CNFSU?kOFSYX~1i z77rF;wb`GDtpf>(B4#^>8X(+&4mxejqR|z&R&$R>yKTfHrOkFxL4wTn8URR(B8Lvp zu8I$K6cM*uEre9QhdQgBZi~4f?jI+kVqQos_J!-9^Dml*&?3MLmsGx`pmUDJOFa}@f`rECJu_PAOIXAQ zjh(h6@ce-$@X{2SZh!F!p$|IGsq6%)i2Dz1!EZ2^W(Rmz_&jc5QBZ__tIsxz|I@F3 z1ezHjz!?#r1WF5=@}=sS^se1K#<}N1*gKMjmmeuEQJ)>Uw@p*Nv%R80@F6I}U*LCh)s> zh6V9(1CRm+a(f?2>0Nu`8tidvq|ass6sFfS_aJ&ee8->I21MF6YaV(suCaJ6AU4s7 zrkgA>r>yeCm>;9YZk}}6EcC8i>Yr+Z#8m3 z2*L7TDl)4nYuHsC$o$z3JFaVyfSF>u#AJIjn?Tb=EopqyTWZ(475HqI9oKT0f0}RI zknq=f1CFDysJQGrjP%ij-NJU%Gl=a#c4rJZ6W4~ydCwh#7BevIL&nA%Ye3+n`#KOY z0l$#1o4PxyIrZVZu$k(F1aR=!hHtqp+oZbjK=(l_l|btPJFFg1{)6&BeL~2M8pU+# zu<#qcW&xvA-6hL*4DMhX%Jw%fJkxNY*5Tj(`bR=flEe#rT9PcQpgi5RX_h4}1@My2 z$8lohF`Wm=hK7_>n>f$n1+fw!ogsP6-jjy8pHdp@x$6}LjlWi_G>D2YO~W9`t0LFw z(znCPj>?DzF^%Tcd1!!?D-8{rue@MRqr&ylVCGPoTE%G)7PML~Q|6lKE$3O8#9ry7 zUKq}4uv|?eFP$V|6t1dOwph<2KO*{~*bsUg!~so$lKP7{?2fQLOR;#&lYQi5(^hb2D2pKjWa*4~Wy1 z&z6hAV@kv7lm=gmC5<8$1(Gf2?9869cVU=^%asR2PQ@a~qGaLB-N1uvO&-w|WhbRz z$D^WS%66ZoWtK2Awb=JU^XtL`PM@$$qh;=&M(mj&Tjqrur~X$qi#RQiv~>h%X@_5DHbvUgP7bLscLmDS&p z>0ci81~r-fp?-0-zPQwmE_&C8I-63zzPR3K!>Xpz*RFc&GfmT>svcPXdl!1u({Gvd zd+X~%pwd68%j%CV9x>@(_6Pd#nt6A|794JXNq>0V>klv4w7{i*IT+}-b@kdn)3qbL z8VsPWesEJ)uWx#T_0`egx_@1x5A1#dF7_e|W>A&jMI!J*cX`yc|^PH4A#x z?+>-J{&4kAgIE4Oejk66ZEIZq#@4E$B--@l9clGj*MR4DMQa)imIekAddTn(_QBZ$zkHGUH)E_=6sT`-{(v)6=&~3U4K|f6lr`aP;Z-H~jKr zsQiy_z-jfIfbP}_PakpSe;1Oc5&~~Z<^1yfI`^rNr-y92oz?bA{Tq-S{s`v2GzT*3 zV4mQ2NNNuh+{ApB{|QOWoljk{i%?H_uOhW04i(IcSQ<$U%+FE*?_(an?;!q93f~nJ zOBKYAJ>2M`eG#{R>KVApDF-~3c+}=w(ms|uc+?V4dPr*mIf>L1kR-L`JxKw@USZf~ zYj6m3UBmnJy8|{5TDr#XYV|*dv8fI>C!%ou|_%CB5D!A9+5Y|65W#*~0!*e3f z%-NF_Ebz?+65Em@>LNc=XHpX%V7!AHO&LjllsTc(RwO~~cSLE>LtL8^#1BXkRjG*@ z9EZ53aPWEOOJ9}*PC#wpor#;$?gw5|x#o-mdE8xIK)j3^s6s@*K(-@DED-FK*H)Ci z^xo=n&4Ga$%&4ZI;uia;-OQvl!i_HtZ0_=%neZ>UMuXXUs0tW=k?>Hca2NeO5_pjt zbs#}Pln)ZZ9iIQ+3NNx)aV$7MfFp>^dBFA6rl9cb>9v4+GMXxgLn8?&_c@;VggY&+ z(@@_t-vn9Y1Z9`QLWhMxfvTehFLR?ICt}=g3A=qBVTs$@;l{XgIBV@UF=`0He@Q%n zm%77-B1w>{z*y)4HBX0U$AgnPZJzD(Qg!fqPWsG??a!R~Noa75U3Dt5u!t%<3~Y6_ zm12kE(>+e*v)z9#@@R;6WW;QTM2pyLw8f#szSr@Bwn6+)|EaBVVq4@s?d=H6-raXS zDN>{_O<)WXKL|WRLPPo!FYF6DYKy&T_0V9Th}>Zlh;n?JxJC_R+P3M|l;OZi0!%J| zgL`iM3DA`L2D@fiz6aW)#4#q*z;{Q1Zw3VT@oOIPv1>yqxOG< zo7I^SfL#GJcRkk(KP?-0v0 z3CPR(H$t_*`vaxy4htf?%XUl_j~RsH@vRy0 zOm@3x>crD#re_n=o5Z9b1hf^VAn$8=H?d@YYPke>l?X`cGAE{;MUQ75Bk zOFgGqvRWlYjSa`%hDL-g%LNTq!MY@b=3$g2NlEh}85?CBM(n;aq#gx|nqd$Y@VjUB2Dw0ZQdqk!KhA7 zoh-^}GEW>*6~%f{y5%ybX=(;x&fF}|5-(nvsaGcXx**igiiDPFxuI@qFQF*?m@d|p zV=U<6r0}5VpVrc|^JSWCXqA>ME_s~N<6vI+$s$;-y;balWtGGZO^6>YbV$vVV_Nvs zwJEU9(^YYjoX{YRPg!8gibh$M?7+pWgkK>F6 z$D7!i=WItaV8Y4DO<0BJRyhxITE&@fReqX6+d!=4;o4;XN@!59qn6G{$W~dfRf074 z{N*~N>y1C7X|WELUPUJhASo-du<$JlRGsM}y@TV|%U}Qeb5Q*C;rP2c^KCHb-zEk8 zdqj`01@_*KFu!x0Z)fAZKVzp{6k|xVAjb#!8S9Ud@DJiHiZ!A~PcC}iv+!9Eym>CGmGO4gy zu-t4>pE0YskS^K9Y{ASJCSD0~BW)(lglVQilT#9=zD!tVl{98EKxYn&oAY|i2;3rF zHiQ+soUutdXX;79LJJUdK5NbwtP-s!Cc?ylP@)Xj@PbtHirHcPQ<^CYtr$m4t@%~S~bT=#0yJrPH9^ZYW z98d19ugCG-2kO3gncV;QK;y~uNfag*Tze{ZPhBpgcKqg5p7QP!%Yz`s7gxFnf``f@ zmYSZmI(|Z}M=w1_gvYo0hLnF=E>EF({B+e$>P)b}r?MYkP$7FKKKzMff@i*kT(Mjv zHgcEB)eWn5rALbtaqB9<zT!qe+fI_aM?^9K}P^b`PI#1<@(ssU9q;?4+Pg4UB zA3hK@xJZy2+gS@D$B>sPDo^Cdy+V!z0k;ZK`BIJ~h@D)4B6cK4`aiKcRe0=ZQwY!~w+Q7+VrV6Z*9 zPHr$nv6QP6u56Q~@&?GWSt$~EHMdhCZV)&3_5q&C4oz(mfFePZYI&kqEEIBe3Sb9R za@1aKpQiF8Mbd?8p_Z#xHb|ldGHw!N5yT~%1$r}26PNNug1WX1w#0M_AZL->WX00u z5>bX*M4kj}in$V7tpd1YzDAWd+jM~?r~+V;D*{MNzEaxTE7vMCnXha%0nebid!@Lw zK~wd2Wlf+i1&|Zf&C=FJahsqn?QRw65~Y-ZWS=gKKe|P1mDGKzR^N_G}rL0>55c#zCV9N*Y-;EW>p0txl%2cyPPWw>lNHdNQT^`$q&E& zk_*F%qnMuS`o88HrsLX%247s?^L!X;Y+cr&j_G-><2kOS3YP48zGXYE?t6}7x|U%$ zp0C@AYI(i_?Oa`TV4Su+7yi>cACE`A4?~r!y1wSQngb18!!`xWkR8hqWtgbBiUZXh z$8+JcY+9}@XpUpMx(Bpuk9P#uQe4}{!<+A!AgAj&mSmZh47FUxg4V9#y0!}MP{#$? zeL=+^HO-R@pkaIqZ6(R2_TG%!^c7tq;p6;ZTo*>qF`zIz%Btd^~tHYn*y4$yNg zQ}ZlCw>42xc~MX;-E{ynte+wqI$!{Z_&&(*xwdY&*?{cG_`V6E$%bL*p6i2*{(6*l zEv$#*SUjKzA51K|V`C|8*OYZ0J{yXPMFqq)*8>40OcqcAnE(vgGI>)KbkV_<(G^+K zEgd*w4569{=)0CENtu=!wxZ*Jj3A%wN|x;cyqf12q9uu{AQ+Mbn1K;B0Mryz%*FIA zQ?xZ(!F|97Dz>0Fj^YWnqw22VxV*}%x@~xt2NnY4EUZ1$1J=OMP+iM`J_Gi19fil8 z#>GYkN{Z*(K2{hgLvOP!Pq0+a7jZv>i;C%kI1Y3b*MQHyZ$St34d2(HFDVkhrbCZ` zYwKx`W@-Sv=kcm(`_REmm?tWhtr?h|VLPBO5VJkg@;$?~u-!a(b@BX3_e~pmtEUkk zd;O(ByNg;V9GT-`A9Ya24Lh@_+X)U^V>@W|6}X0+w$p6|14C}R&H#0Xt;p-N`avhY zrKYGe>QC&zLC|eY+dx`(=#Nmxhzv9v_U#09{IrV(L(M_9J#PD`H9+H}b08z5kD|U4 zje0W3=vzqbkGh@FNDF)yby`t^Lf=ffy-vqLZWno|V~v6+9*xJH&d{+(y>ZLxqOsdH z+CATG_1a!Mh4a}l2!Fr)qHy9w)N8Q5#5J2sN!KB>^hk*yW_T6!( z)k4UR5HfFELL`v|q|LD=n~DE9nLx2GEj+15%3;%I=yxf1yQ>nK=T%85TP&%ddTxzXxJSOTccLT z_fR2PSFQP3T?>}Z5~#$bj1-ZE*s` zy2GJ6_DADr7)A+*3yQVI6U*v*gKpa!IK80VNl~lc3mr7L6}TuwfG?C$$M4Qux7&?| zBa~WE5Ae`Opm9g@dV|pEcR(c+bVCmfA`kR6z)HwKhfWuDLD-2q?zcMaFc@|wrjCp* zLY?987Q7;F6pT@~-EK{yR?82K6xmMC?pg2;&oCJFx^5bw-e}xMVJGRe^$4|13fHiR)r)AqFg1**69UCEch!9XQUR55~8K!BdxuRF}UQg2eZI?3Vh=B=NpaP3Z4_{exe<^WG7~KI(T~`Y`lz_<*b>eaU*6^ZqZ!Evvl6T-aLRlUHy10mnKaYJf@44=w#jhuicJ-kYt$8nUDW4`q^Ydtt5jfP zrqNg}W^sd?2_OK=FwlUVv-KrYUpC?elQ2xu#BDe(S#ip2wEz|kPKZ~FBu!$_X;E(| z>}h| zW|7R7fW(4bC7@9~O`#pLSaHHqSS{H&Uapo6U<-5;0SGY7=0cd&8>{iR$MN}Ad8_;z zP%iY(KUlCoSGFFysGfJ}O2UKA%_o*O_qIOF>tWjWS>v_A+Rv&y!QK0?SZ^Zc!~StB zuyFx%J*)bNH~k^~)brmT_JbP_eLt;WK3PKVF*@iEO7kFfS2qY^5&H;^!}b}cKpD_-F@dcmG5sg80_?d9${o)^~G-97PnVYN0}vD3UI26bf58wzQou6sy(pHdUxpXp*Ms zLXq4es~bh4P|h(lRobr?$y|jbY7|9NB$3;v3Ogjl2@iij47A% zM5S^&pTAOt8*KiI)%?%pt!n8KU7&M0B44CwDtCp9=)!KUUa1sv*ilUoRbn&Os1mtc zzFH>9*-gyq-CMO>vE0p-3Y)-dyKt?fs(HFVRq|B6n#-5B>iOM`JPGvZa-mu&ReVrz zXOG?{sRB{rHeuaf&l8|juGZKhh%!*4==@HFE)x}s_@R7}$d!d!rBKLUy;aGR#SMbm zq;gw1YAY|&Vu9Ww3I(3dmC6)ZX%tyvyO4j!CRJugD!;K=q3cv_xiQ(zZ*7tr1wzV` zRI^YoUn%Yoh5Uw4DQ;XYko6pKQzi?$WVuqH>bX&#pr~rTN`f@9n=4)~kXH_C2m9m= zimK%D_1bp6O6Q6t?tq}5EfB=kb-LIn0A&!WSfw`cC5oVH#3ofEa8w)Ev86{R)*E z*NXWojqS#MnI09cgYb>*0(JS79hTfA3#DypvrbWkyjZA_zUSGJ?c2VO>BFCH`MzU&p0De+YwD`2sg|v(mTOy*?&-dY zD|tAm098ER^<))$#9h}lJ<${;#n2tcaXnLTG}F=?+tPFx>n-dW_I1O@!s5@e?}8*y z$8jy7<>@MrHGIdzVG7Gp@G$Kk);V#3G{_x#M&EQ-9NI)DsJ9c|z8M8lC?$1)T^M#TI*PcU8E zHFQ-0j4WSw49~Iv17M|l8A|JE3r5VdY-nejqGtP!1>bQ@#K8Ad2?OH@P8PB-TwPHe zS?77%&H@ImCK)DgYmTe}-ma;7s%h}R&w=@}?YI~YU-vD?z?S!PSp!pMaUFoy@u7_k z2=LkT!vzBx5};)Qs=n>`peiWrW$tv>aUIPP9l#y?%w3=e?SYVh6|yB@0A}`lM>VnX zstbJzJNkK>*F6jFz!WHpab$nM-Lg!@1z|l!Q}G1c#9H&ZoB8rH1l;wTpYeAr5#%

    iTd}R5y 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 literal 0 HcmV?d00001 diff --git a/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.1.subreads.bam.pbi b/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.1.subreads.bam.pbi new file mode 100644 index 0000000000000000000000000000000000000000..cc9f24feda59a13f7ff1ce430685db0fa1756110 GIT binary patch literal 4293 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 literal 0 HcmV?d00001 diff --git a/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.2.subreads.bam b/tests/data/chunking/m150404_101626_42267_c100807920800000001823174110291514_s1_p0.2.subreads.bam new file mode 100644 index 0000000000000000000000000000000000000000..2a8e7e0cdd0440ec660997d5f5f6b02fc751e7e2 GIT binary patch literal 977970 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