[med-svn] [htsjdk] 01/01: Re-add file SAMFileReader.java featuring an outdated API which is used by Artemis and FastQC
Andreas Tille
tille at debian.org
Mon Dec 5 14:57:28 UTC 2016
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository htsjdk.
commit 2ea9ded0d13a9e45b44423d9efa4ca8eb39f1c1a
Author: Andreas Tille <tille at debian.org>
Date: Mon Dec 5 15:57:08 2016 +0100
Re-add file SAMFileReader.java featuring an outdated API which is used by Artemis and FastQC
---
debian/changelog | 8 +
debian/patches/add_lost_SAMFileReader.java.patch | 767 +++++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 776 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index cb0f147..de3755a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+htsjdk (2.7.0+dfsg-3) UNRELEASED; urgency=medium
+
+ * Re-add file SAMFileReader.java featuring an outdated API which is
+ used by Artemis and FastQC
+ Closes: #846708, #846671
+
+ -- Andreas Tille <tille at debian.org> Mon, 05 Dec 2016 12:55:27 +0100
+
htsjdk (2.7.0+dfsg-2) unstable; urgency=medium
* Fix mess in this changelog (the previous upload is missing the
diff --git a/debian/patches/add_lost_SAMFileReader.java.patch b/debian/patches/add_lost_SAMFileReader.java.patch
new file mode 100644
index 0000000..82e1a3d
--- /dev/null
+++ b/debian/patches/add_lost_SAMFileReader.java.patch
@@ -0,0 +1,767 @@
+Author: Andreas Tille <tille at debian.org>
+Last-Update: Mon, 05 Dec 2016 12:55:27 +0100
+Bug-Debian: https://bugs.debian.org/846671
+ https://bugs.debian.org/846708
+Description: Upstream has changed the API to read SAM files.
+ As upstream explains in #767
+ https://github.com/samtools/htsjdk/issues/767
+ FastQC and Artemis should switch to the new API.
+ .
+ However, as long as this has not happened yet restoring the old file
+ src/main/java/htsjdk/samtools/SAMFileReader.java
+ fixes the FTBFS errors of both packages.
+
+--- /dev/null
++++ b/src/main/java/htsjdk/samtools/SAMFileReader.java
+@@ -0,0 +1,751 @@
++/*
++ * The MIT License
++ *
++ * Copyright (c) 2009 The Broad Institute
++ *
++ * 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.
++ */
++package htsjdk.samtools;
++
++
++import htsjdk.samtools.seekablestream.SeekableBufferedStream;
++import htsjdk.samtools.seekablestream.SeekableHTTPStream;
++import htsjdk.samtools.seekablestream.SeekableStream;
++import htsjdk.samtools.util.*;
++
++import java.io.*;
++import java.net.URL;
++import java.util.NoSuchElementException;
++import java.util.zip.GZIPInputStream;
++
++/**
++ * Class for reading and querying SAM/BAM files. Delegates to appropriate concrete implementation.
++ *
++ * @see SamReaderFactory
++ */
++ at Deprecated
++public class SAMFileReader implements SamReader, SamReader.Indexing {
++
++ private static ValidationStringency defaultValidationStringency = ValidationStringency.DEFAULT_STRINGENCY;
++
++ public static ValidationStringency getDefaultValidationStringency() {
++ return defaultValidationStringency;
++ }
++
++ /**
++ * Set validation stringency for all subsequently-created SAMFileReaders. This is the only way to
++ * change the validation stringency for SAM header.
++ * NOTE: Programs that change this should make sure to have a try/finally clause wrapping the work that
++ * they do, so that the original stringency can be restored after the program's work is done. This facilitates
++ * calling a program that is usually run stand-alone from another program, without messing up the original
++ * validation stringency.
++ */
++ public static void setDefaultValidationStringency(final ValidationStringency defaultValidationStringency) {
++ SAMFileReader.defaultValidationStringency = defaultValidationStringency;
++ }
++
++ /**
++ * Returns the SAMSequenceDictionary from the provided FASTA.
++ */
++ public static SAMSequenceDictionary getSequenceDictionary(final File dictionaryFile) {
++ final SAMFileReader samFileReader = new SAMFileReader(dictionaryFile);
++ final SAMSequenceDictionary dict = samFileReader.getFileHeader().getSequenceDictionary();
++ CloserUtil.close(dictionaryFile);
++ return dict;
++ }
++
++ private boolean mIsBinary = false;
++ private BAMIndex mIndex = null;
++ private SAMRecordFactory samRecordFactory = new DefaultSAMRecordFactory();
++ private ReaderImplementation mReader = null;
++ private boolean useAsyncIO = Defaults.USE_ASYNC_IO_READ_FOR_SAMTOOLS;
++
++ private File samFile = null;
++
++ private static class EmptySamIterator implements CloseableIterator<SAMRecord> {
++ @Override
++ public boolean hasNext() {
++ return false;
++ }
++
++ @Override
++ public SAMRecord next() {
++ throw new NoSuchElementException("next called on empty iterator");
++ }
++
++ @Override
++ public void remove() {
++ throw new UnsupportedOperationException("Not supported: remove");
++ }
++
++ @Override
++ public void close() {
++ //no-op
++ }
++ }
++
++
++ /**
++ * Prepare to read a SAM or BAM file. Indexed lookup not allowed because reading from InputStream.
++ */
++ public SAMFileReader(final InputStream stream) {
++ this(stream, false);
++ }
++
++ /**
++ * Prepare to read a SAM or BAM file. If the given file is a BAM, and has a companion BAI index file
++ * that is named according to the convention, it will be found and opened, and indexed query will be allowed.
++ */
++ public SAMFileReader(final File file) {
++ this(file, null, false);
++ }
++
++ /**
++ * Prepare to read a SAM or BAM file. If the given file is a BAM, and an index is present, indexed query
++ * will be allowed.
++ *
++ * @param file SAM or BAM to read.
++ * @param indexFile Index file that is companion to BAM, or null if no index file, or if index file
++ * should be found automatically.
++ */
++ public SAMFileReader(final File file, final File indexFile) {
++ this(file, indexFile, false);
++ }
++
++ /**
++ * Read a SAM or BAM file. Indexed lookup not allowed because reading from InputStream.
++ *
++ * @param stream input SAM or BAM. This is buffered internally so caller need not buffer.
++ * @param eagerDecode if true, decode SAM record entirely when reading it.
++ */
++ public SAMFileReader(final InputStream stream, final boolean eagerDecode) {
++ init(stream, null, null, eagerDecode, defaultValidationStringency);
++ }
++
++ /**
++ * Read a SAM or BAM file, possibly with an index file if present.
++ * If the given file is a BAM, and an index is present, indexed query will be allowed.
++ *
++ * @param file SAM or BAM.
++ * @param eagerDecode if true, decode SAM record entirely when reading it.
++ */
++ public SAMFileReader(final File file, final boolean eagerDecode) {
++ this(file, null, eagerDecode);
++ }
++
++ /**
++ * Read a SAM or BAM file, possibly with an index file. If the given file is a BAM, and an index is present,
++ * indexed query will be allowed.
++ *
++ * @param file SAM or BAM.
++ * @param indexFile Location of index file, or null in order to use the default index file (if present).
++ * @param eagerDecode eagerDecode if true, decode SAM record entirely when reading it.
++ */
++ public SAMFileReader(final File file, final File indexFile, final boolean eagerDecode) {
++ init(null, file, indexFile, eagerDecode, defaultValidationStringency);
++ }
++
++ /**
++ * Read a BAM file by http
++ * indexed query will be allowed.
++ *
++ * @param url BAM.
++ * @param indexFile Location of index file, or null if indexed access not required.
++ * @param eagerDecode eagerDecode if true, decode SAM record entirely when reading it.
++ */
++ public SAMFileReader(final URL url, final File indexFile, final boolean eagerDecode) {
++ init(new SeekableBufferedStream(new SeekableHTTPStream(url)),
++ indexFile, eagerDecode, defaultValidationStringency);
++ }
++
++ /**
++ * Read a BAM file via caller-supplied mechanism. Indexed query will be allowed, but
++ * index file must be provided in that case.
++ *
++ * @param strm BAM -- If the stream is not buffered, caller should wrap in SeekableBufferedStream for
++ * better performance.
++ * @param indexFile Location of index file, or null indexed access not required.
++ * @param eagerDecode if true, decode SAM record entirely when reading it.
++ */
++ public SAMFileReader(final SeekableStream strm, final File indexFile, final boolean eagerDecode) {
++ init(strm, indexFile, eagerDecode, defaultValidationStringency);
++ }
++
++ /**
++ * @param strm BAM -- If the stream is not buffered, caller should wrap in SeekableBufferedStream for
++ * better performance.
++ */
++ public SAMFileReader(final SeekableStream strm, final SeekableStream indexStream, final boolean eagerDecode) {
++ init(strm, indexStream, eagerDecode, defaultValidationStringency);
++ }
++
++ public void close() {
++ if (mReader != null) {
++ mReader.close();
++ }
++ mReader = null;
++ mIndex = null;
++ }
++
++ /**
++ * If true, this reader will use asynchronous IO.
++ */
++ public void setUseAsyncIO(final boolean useAsyncIO) {
++ this.useAsyncIO = useAsyncIO;
++ }
++
++ /**
++ * If true, writes the source of every read into the source SAMRecords.
++ *
++ * @param enabled true to write source information into each SAMRecord.
++ */
++ public void enableFileSource(final boolean enabled) {
++ mReader.enableFileSource(this, enabled);
++ }
++
++ /**
++ * If true, uses the caching version of the index reader.
++ *
++ * @param enabled true to use the caching version of the reader.
++ */
++ public void enableIndexCaching(final boolean enabled) {
++ if (mIndex != null)
++ throw new SAMException("Unable to turn on index caching; index file has already been loaded.");
++ mReader.enableIndexCaching(enabled);
++ }
++
++ /**
++ * If false, disable the use of memory mapping for accessing index files (default behavior is to use memory mapping).
++ * This is slower but more scalable when accessing large numbers of BAM files sequentially.
++ *
++ * @param enabled True to use memory mapping, false to use regular I/O.
++ */
++ public void enableIndexMemoryMapping(final boolean enabled) {
++ if (mIndex != null) {
++ throw new SAMException("Unable to change index memory mapping; index file has already been loaded.");
++ }
++ mReader.enableIndexMemoryMapping(enabled);
++ }
++
++ /**
++ * Only meaningful for BAM file readers - enables or disables checking of checksums on uncompressed
++ * data during decompression. Enabling this will increase decompression time by 15-30%.
++ */
++ public void enableCrcChecking(final boolean enabled) {
++ this.mReader.enableCrcChecking(enabled);
++ }
++
++ /**
++ * Override the default SAMRecordFactory class used to instantiate instances of SAMRecord and BAMRecord.
++ */
++ public void setSAMRecordFactory(final SAMRecordFactory factory) {
++ this.samRecordFactory = factory;
++ this.mReader.setSAMRecordFactory(factory);
++ }
++
++ /**
++ * @return True if this is a BAM reader.
++ */
++ public boolean isBinary() {
++ return mIsBinary;
++ }
++
++ /**
++ * @return true if ths is a BAM file, and has an index
++ */
++ public boolean hasIndex() {
++ return mReader.hasIndex();
++ }
++
++ @Override
++ public Indexing indexing() {
++ return this;
++ }
++
++ /**
++ * Retrieves the index for the given file type. Ensure that the index is of the specified type.
++ *
++ * @return An index of the given type.
++ */
++ public BAMIndex getIndex() {
++ return mReader.getIndex();
++ }
++
++ /**
++ * Returns true if the supported index is browseable, meaning the bins in it can be traversed
++ * and chunk data inspected and retrieved.
++ *
++ * @return True if the index supports the BrowseableBAMIndex interface. False otherwise.
++ */
++ public boolean hasBrowseableIndex() {
++ return hasIndex() && getIndex() instanceof BrowseableBAMIndex;
++ }
++
++ /**
++ * Gets an index tagged with the BrowseableBAMIndex interface. Throws an exception if no such
++ * index is available.
++ *
++ * @return An index with a browseable interface, if possible.
++ * @throws SAMException if no such index is available.
++ */
++ public BrowseableBAMIndex getBrowseableIndex() {
++ final BAMIndex index = getIndex();
++ if (!(index instanceof BrowseableBAMIndex))
++ throw new SAMException("Cannot return index: index created by BAM is not browseable.");
++ return BrowseableBAMIndex.class.cast(index);
++ }
++
++ public SAMFileHeader getFileHeader() {
++ return mReader.getFileHeader();
++ }
++
++ @Override
++ public Type type() {
++ return mReader.type();
++ }
++
++ @Override
++ public String getResourceDescription() {
++ return this.toString();
++ }
++
++ /**
++ * Control validation of SAMRecords as they are read from file.
++ * In order to control validation stringency for SAM Header, call SAMFileReader.setDefaultValidationStringency
++ * before constructing a SAMFileReader.
++ */
++ public void setValidationStringency(final ValidationStringency validationStringency) {
++ mReader.setValidationStringency(validationStringency);
++ }
++
++ /**
++ * Iterate through file in order. For a SAMFileReader constructed from an InputStream, and for any SAM file,
++ * a 2nd iteration starts where the 1st one left off. For a BAM constructed from a File, each new iteration
++ * starts at the first record.
++ * <p/>
++ * Only a single open iterator on a SAM or BAM file may be extant at any one time. If you want to start
++ * a second iteration, the first one must be closed first.
++ */
++ public SAMRecordIterator iterator() {
++ return new AssertingIterator(mReader.getIterator());
++ }
++
++ /**
++ * Iterate through the given chunks in the file.
++ *
++ * @param chunks List of chunks for which to retrieve data.
++ * @return An iterator over the given chunks.
++ */
++ public SAMRecordIterator iterator(final SAMFileSpan chunks) {
++ return new AssertingIterator(mReader.getIterator(chunks));
++ }
++
++ /**
++ * Gets a pointer spanning all reads in the BAM file.
++ *
++ * @return Unbounded pointer to the first record, in chunk format.
++ */
++ public SAMFileSpan getFilePointerSpanningReads() {
++ return mReader.getFilePointerSpanningReads();
++ }
++
++ /**
++ * Iterate over records that match the given interval. Only valid to call this if hasIndex() == true.
++ * <p/>
++ * Only a single open iterator on a given SAMFileReader may be extant at any one time. If you want to start
++ * a second iteration, the first one must be closed first. You can use a second SAMFileReader to iterate
++ * in parallel over the same underlying file.
++ * <p/>
++ * Note that indexed lookup is not perfectly efficient in terms of disk I/O. I.e. some SAMRecords may be read
++ * and then discarded because they do not match the interval of interest.
++ * <p/>
++ * Note that an unmapped read will be returned by this call if it has a coordinate for the purpose of sorting that
++ * is in the query region.
++ *
++ * @param sequence Reference sequence of interest.
++ * @param start 1-based, inclusive start of interval of interest. Zero implies start of the reference sequence.
++ * @param end 1-based, inclusive end of interval of interest. Zero implies end of the reference sequence.
++ * @param contained If true, each SAMRecord returned is will have its alignment completely contained in the
++ * interval of interest. If false, the alignment of the returned SAMRecords need only overlap the interval of interest.
++ * @return Iterator over the SAMRecords matching the interval.
++ */
++ public SAMRecordIterator query(final String sequence, final int start, final int end, final boolean contained) {
++ final int referenceIndex = getFileHeader().getSequenceIndex(sequence);
++ final CloseableIterator<SAMRecord> currentIterator;
++ if (referenceIndex == -1) {
++ currentIterator = new EmptySamIterator();
++ } else {
++ final QueryInterval[] queryIntervals = {new QueryInterval(referenceIndex, start, end)};
++ currentIterator = mReader.query(queryIntervals, contained);
++ }
++ return new AssertingIterator(currentIterator);
++ }
++
++ /**
++ * Iterate over records that overlap the given interval. Only valid to call this if hasIndex() == true.
++ * <p/>
++ * Only a single open iterator on a given SAMFileReader may be extant at any one time. If you want to start
++ * a second iteration, the first one must be closed first.
++ * <p/>
++ * Note that indexed lookup is not perfectly efficient in terms of disk I/O. I.e. some SAMRecords may be read
++ * and then discarded because they do not match the interval of interest.
++ * <p/>
++ * Note that an unmapped read will be returned by this call if it has a coordinate for the purpose of sorting that
++ * is in the query region.
++ *
++ * @param sequence Reference sequence of interest.
++ * @param start 1-based, inclusive start of interval of interest. Zero implies start of the reference sequence.
++ * @param end 1-based, inclusive end of interval of interest. Zero implies end of the reference sequence.
++ * @return Iterator over the SAMRecords overlapping the interval.
++ */
++ public SAMRecordIterator queryOverlapping(final String sequence, final int start, final int end) {
++ return query(sequence, start, end, false);
++ }
++
++ /**
++ * Iterate over records that are contained in the given interval. Only valid to call this if hasIndex() == true.
++ * <p/>
++ * Only a single open iterator on a given SAMFileReader may be extant at any one time. If you want to start
++ * a second iteration, the first one must be closed first.
++ * <p/>
++ * Note that indexed lookup is not perfectly efficient in terms of disk I/O. I.e. some SAMRecords may be read
++ * and then discarded because they do not match the interval of interest.
++ * <p/>
++ * Note that an unmapped read will be returned by this call if it has a coordinate for the purpose of sorting that
++ * is in the query region.
++ *
++ * @param sequence Reference sequence of interest.
++ * @param start 1-based, inclusive start of interval of interest. Zero implies start of the reference sequence.
++ * @param end 1-based, inclusive end of interval of interest. Zero implies end of the reference sequence.
++ * @return Iterator over the SAMRecords contained in the interval.
++ */
++ public SAMRecordIterator queryContained(final String sequence, final int start, final int end) {
++ return query(sequence, start, end, true);
++ }
++
++ /**
++ * Iterate over records that match one of the given intervals. This may be more efficient than querying
++ * each interval separately, because multiple reads of the same SAMRecords is avoided.
++ * <p/>
++ * Only valid to call this if hasIndex() == true.
++ * <p/>
++ * Only a single open iterator on a given SAMFileReader may be extant at any one time. If you want to start
++ * a second iteration, the first one must be closed first. You can use a second SAMFileReader to iterate
++ * in parallel over the same underlying file.
++ * <p/>
++ * Note that indexed lookup is not perfectly efficient in terms of disk I/O. I.e. some SAMRecords may be read
++ * and then discarded because they do not match an interval of interest.
++ * <p/>
++ * Note that an unmapped read will be returned by this call if it has a coordinate for the purpose of sorting that
++ * is in the query region.
++ *
++ * @param intervals Intervals to be queried. The intervals must be optimized, i.e. in order, with overlapping
++ * and abutting intervals merged. This can be done with {@link htsjdk.samtools.QueryInterval#optimizeIntervals}
++ * @param contained If true, each SAMRecord returned is will have its alignment completely contained in one of the
++ * intervals of interest. If false, the alignment of the returned SAMRecords need only overlap one of
++ * the intervals of interest.
++ * @return Iterator over the SAMRecords matching the interval.
++ */
++ public SAMRecordIterator query(final QueryInterval[] intervals, final boolean contained) {
++ return new AssertingIterator(mReader.query(intervals, contained));
++ }
++
++ /**
++ * Iterate over records that overlap any of the given intervals. This may be more efficient than querying
++ * each interval separately, because multiple reads of the same SAMRecords is avoided.
++ * <p/>
++ * Only valid to call this if hasIndex() == true.
++ * <p/>
++ * Only a single open iterator on a given SAMFileReader may be extant at any one time. If you want to start
++ * a second iteration, the first one must be closed first.
++ * <p/>
++ * Note that indexed lookup is not perfectly efficient in terms of disk I/O. I.e. some SAMRecords may be read
++ * and then discarded because they do not match the interval of interest.
++ * <p/>
++ * Note that an unmapped read will be returned by this call if it has a coordinate for the purpose of sorting that
++ * is in the query region.
++ *
++ * @param intervals Intervals to be queried. The intervals must be optimized, i.e. in order, with overlapping
++ * and abutting intervals merged. This can be done with {@link htsjdk.samtools.QueryInterval#optimizeIntervals}
++ * @return Iterator over the SAMRecords overlapping any of the intervals.
++ */
++ public SAMRecordIterator queryOverlapping(final QueryInterval[] intervals) {
++ return query(intervals, false);
++ }
++
++ /**
++ * Iterate over records that are contained in the given interval. This may be more efficient than querying
++ * each interval separately, because multiple reads of the same SAMRecords is avoided.
++ * <p/>
++ * Only valid to call this if hasIndex() == true.
++ * <p/>
++ * Only a single open iterator on a given SAMFileReader may be extant at any one time. If you want to start
++ * a second iteration, the first one must be closed first.
++ * <p/>
++ * Note that indexed lookup is not perfectly efficient in terms of disk I/O. I.e. some SAMRecords may be read
++ * and then discarded because they do not match the interval of interest.
++ * <p/>
++ * Note that an unmapped read will be returned by this call if it has a coordinate for the purpose of sorting that
++ * is in the query region.
++ *
++ * @param intervals Intervals to be queried. The intervals must be optimized, i.e. in order, with overlapping
++ * and abutting intervals merged. This can be done with {@link htsjdk.samtools.QueryInterval#optimizeIntervals}
++ * @return Iterator over the SAMRecords contained in any of the intervals.
++ */
++ public SAMRecordIterator queryContained(final QueryInterval[] intervals) {
++ return query(intervals, true);
++ }
++
++
++ public SAMRecordIterator queryUnmapped() {
++ return new AssertingIterator(mReader.queryUnmapped());
++ }
++
++ /**
++ * Iterate over records that map to the given sequence and start at the given position. Only valid to call this if hasIndex() == true.
++ * <p/>
++ * Only a single open iterator on a given SAMFileReader may be extant at any one time. If you want to start
++ * a second iteration, the first one must be closed first.
++ * <p/>
++ * Note that indexed lookup is not perfectly efficient in terms of disk I/O. I.e. some SAMRecords may be read
++ * and then discarded because they do not match the interval of interest.
++ * <p/>
++ * Note that an unmapped read will be returned by this call if it has a coordinate for the purpose of sorting that
++ * matches the arguments.
++ *
++ * @param sequence Reference sequence of interest.
++ * @param start Alignment start of interest.
++ * @return Iterator over the SAMRecords with the given alignment start.
++ */
++ public SAMRecordIterator queryAlignmentStart(final String sequence, final int start) {
++ return new AssertingIterator(mReader.queryAlignmentStart(sequence, start));
++ }
++
++ /**
++ * Fetch the mate for the given read. Only valid to call this if hasIndex() == true.
++ * This will work whether the mate has a coordinate or not, so long as the given read has correct
++ * mate information. This method iterates over the SAM file, so there may not be an unclosed
++ * iterator on the SAM file when this method is called.
++ * <p/>
++ * Note that it is not possible to call queryMate when iterating over the SAMFileReader, because queryMate
++ * requires its own iteration, and there cannot be two simultaneous iterations on the same SAMFileReader. The
++ * work-around is to open a second SAMFileReader on the same input file, and call queryMate on the second
++ * reader.
++ *
++ * @param rec Record for which mate is sought. Must be a paired read.
++ * @return rec's mate, or null if it cannot be found.
++ */
++ public SAMRecord queryMate(final SAMRecord rec) {
++ if (!rec.getReadPairedFlag()) {
++ throw new IllegalArgumentException("queryMate called for unpaired read.");
++ }
++ if (rec.getFirstOfPairFlag() == rec.getSecondOfPairFlag()) {
++ throw new IllegalArgumentException("SAMRecord must be either first and second of pair, but not both.");
++ }
++ final boolean firstOfPair = rec.getFirstOfPairFlag();
++ final CloseableIterator<SAMRecord> it;
++ if (rec.getMateReferenceIndex() == SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX) {
++ it = queryUnmapped();
++ } else {
++ it = queryAlignmentStart(rec.getMateReferenceName(), rec.getMateAlignmentStart());
++ }
++ try {
++ SAMRecord mateRec = null;
++ while (it.hasNext()) {
++ final SAMRecord next = it.next();
++ if (!next.getReadPairedFlag()) {
++ if (rec.getReadName().equals(next.getReadName())) {
++ throw new SAMFormatException("Paired and unpaired reads with same name: " + rec.getReadName());
++ }
++ continue;
++ }
++ if (firstOfPair) {
++ if (next.getFirstOfPairFlag()) continue;
++ } else {
++ if (next.getSecondOfPairFlag()) continue;
++ }
++ if (rec.getReadName().equals(next.getReadName())) {
++ if (mateRec != null) {
++ throw new SAMFormatException("Multiple SAMRecord with read name " + rec.getReadName() +
++ " for " + (firstOfPair ? "second" : "first") + " end.");
++ }
++ mateRec = next;
++ }
++ }
++ return mateRec;
++ } finally {
++ it.close();
++ }
++ }
++
++
++ private void init(final SeekableStream strm, final File indexFile, final boolean eagerDecode,
++ final ValidationStringency validationStringency) {
++
++ try {
++ if (streamLooksLikeBam(strm)) {
++ mIsBinary = true;
++ mReader = new BAMFileReader(strm, indexFile, eagerDecode, useAsyncIO, validationStringency, this.samRecordFactory);
++ } else {
++ throw new SAMFormatException("Unrecognized file format: " + strm);
++ }
++ setValidationStringency(validationStringency);
++ } catch (final IOException e) {
++ throw new RuntimeIOException(e);
++ }
++ }
++
++ private void init(final SeekableStream strm, final SeekableStream indexStream, final boolean eagerDecode,
++ final ValidationStringency validationStringency) {
++
++ try {
++ if (streamLooksLikeBam(strm)) {
++ mIsBinary = true;
++ mReader = new BAMFileReader(strm, indexStream, eagerDecode, useAsyncIO, validationStringency, this.samRecordFactory);
++ } else {
++ throw new SAMFormatException("Unrecognized file format: " + strm);
++ }
++ setValidationStringency(validationStringency);
++ } catch (final IOException e) {
++ throw new RuntimeIOException(e);
++ }
++ }
++
++ // Its too expensive to examine the remote file to determine type.
++ // Rely on file extension.
++ private boolean streamLooksLikeBam(final SeekableStream strm) {
++ String source = strm.getSource();
++ if (source == null) return true;
++ source = source.toLowerCase();
++ //Source will typically be a file path or URL
++ //If it's a URL we require one of the query parameters to be bam file
++ return source.endsWith(".bam") || source.contains(".bam?") || source.contains(".bam&") || source.contains(".bam%26");
++ }
++
++ private void init(final InputStream stream, File file, final File indexFile, final boolean eagerDecode,
++ final ValidationStringency validationStringency) {
++ if (stream != null && file != null) throw new IllegalArgumentException("stream and file are mutually exclusive");
++ this.samFile = file;
++
++ try {
++ BufferedInputStream bufferedStream;
++ // Buffering is required because mark() and reset() are called on the input stream.
++ final int bufferSize = Math.max(Defaults.BUFFER_SIZE, BlockCompressedStreamConstants.MAX_COMPRESSED_BLOCK_SIZE);
++ if (file != null) bufferedStream = new BufferedInputStream(new FileInputStream(file), bufferSize);
++ else bufferedStream = IOUtil.toBufferedStream(stream);
++ if (SamStreams.isBAMFile(bufferedStream)) {
++ mIsBinary = true;
++ if (file == null || !file.isFile()) {
++ // Handle case in which file is a named pipe, e.g. /dev/stdin or created by mkfifo
++ mReader = new BAMFileReader(bufferedStream, indexFile, eagerDecode, useAsyncIO, validationStringency, this.samRecordFactory);
++ } else {
++ bufferedStream.close();
++ mReader = new BAMFileReader(file, indexFile, eagerDecode, useAsyncIO, validationStringency, this.samRecordFactory);
++ }
++ } else if (BlockCompressedInputStream.isValidFile(bufferedStream)) {
++ mIsBinary = false;
++ mReader = new SAMTextReader(new BlockCompressedInputStream(bufferedStream), validationStringency, this.samRecordFactory);
++ } else if (SamStreams.isGzippedSAMFile(bufferedStream)) {
++ mIsBinary = false;
++ mReader = new SAMTextReader(new GZIPInputStream(bufferedStream), validationStringency, this.samRecordFactory);
++ } else if (SamStreams.isCRAMFile(bufferedStream)) {
++ if (file == null || !file.isFile()) {
++ file = null;
++ } else {
++ bufferedStream.close();
++ bufferedStream = null;
++ }
++ mReader = new CRAMFileReader(file, bufferedStream);
++ } else if (isSAMFile(bufferedStream)) {
++ if (indexFile != null) {
++ bufferedStream.close();
++ throw new RuntimeException("Cannot use index file with textual SAM file");
++ }
++ mIsBinary = false;
++ mReader = new SAMTextReader(bufferedStream, file, validationStringency, this.samRecordFactory);
++ } else {
++ bufferedStream.close();
++ throw new SAMFormatException("Unrecognized file format");
++ }
++
++ setValidationStringency(validationStringency);
++ mReader.setSAMRecordFactory(this.samRecordFactory);
++ } catch (final IOException e) {
++ throw new RuntimeIOException(e);
++ }
++ }
++
++ private static int readBytes(final InputStream stream, final byte[] buffer, final int offset, final int length)
++ throws IOException {
++ int bytesRead = 0;
++ while (bytesRead < length) {
++ final int count = stream.read(buffer, offset + bytesRead, length - bytesRead);
++ if (count <= 0) {
++ break;
++ }
++ bytesRead += count;
++ }
++ return bytesRead;
++ }
++
++ private boolean isSAMFile(final InputStream stream) {
++ // For now, assume every non-binary file is a SAM text file.
++ return true;
++ }
++
++ @Override
++ public String toString() {
++ if (this.samFile == null) {
++ return getClass().getSimpleName() + "{initialized with stream}";
++ } else {
++ return getClass().getSimpleName() + "{" + this.samFile.getAbsolutePath() + "}";
++ }
++ }
++
++ /**
++ * Convenience method to create a QueryInterval
++ *
++ * @param sequence sequence of interest, must exist in sequence dictionary
++ * @param start 1-based start position, must be >= 1
++ * @param end 1-based end position.
++ * @throws java.lang.IllegalArgumentException if sequence not found in sequence dictionary, or start position < 1
++ */
++ public QueryInterval makeQueryInterval(final String sequence, int start, int end) {
++ int referenceIndex = getFileHeader().getSequenceIndex(sequence);
++ if (referenceIndex < 0) {
++ throw new IllegalArgumentException(String.format("Sequence '%s' not found in sequence dictionary", sequence));
++ }
++ if (start < 1) {
++ throw new IllegalArgumentException("Start position must be >= 1");
++ }
++ return new QueryInterval(referenceIndex, start, end);
++ }
++
++ /**
++ * Convenience method to create a QueryInterval that goes from start to end of given sequence.
++ *
++ * @param sequence sequence of interest, must exist in sequence dictionary
++ * @param start 1-based start position, must be >= 1
++ * @throws java.lang.IllegalArgumentException if sequence not found in sequence dictionary, or start position < 1
++ */
++ public QueryInterval makeQueryInterval(final String sequence, int start) {
++ return makeQueryInterval(sequence, start, 0);
++ }
++
++}
diff --git a/debian/patches/series b/debian/patches/series
index 1a7872a..670b29f 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -2,3 +2,4 @@
11-snappy-java-compatibility.patch
13-skip_network_tests
20-fix-version.patch
+add_lost_SAMFileReader.java.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/htsjdk.git
More information about the debian-med-commit
mailing list