All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.broadinstitute.hellbender.tools.dragstr.BufferedReferenceBases Maven / Gradle / Ivy

The newest version!
package org.broadinstitute.hellbender.tools.dragstr;

import htsjdk.samtools.SAMSequenceRecord;
import org.broadinstitute.hellbender.engine.ReferenceDataSource;
import org.broadinstitute.hellbender.utils.Utils;
import org.broadinstitute.hellbender.utils.param.ParamUtils;

/**
 * Buffered access to long reference sequences.
 * 

* Allows to access the whole contig sequence down to a single base at a time without worrying about loading the next frame. *

* Allows contiguous access of individual bases for down to a single base retrieval loading more bases from the underlying sequence as needed. *

* It keep a copy of the previous loaded section in case there some additional bases up-stream are requested. *

*

* This complements any buffering that might be provided by the underlying {@link ReferenceDataSource}. *

*/ final class BufferedReferenceBases { private final String contigID; private final long length; private int bufferSize; private byte[] buffer; private byte[] previousBuffer; private final ReferenceDataSource dataSource; private long bufferStart; private long bufferEnd; private BufferedReferenceBases(final ReferenceDataSource dataSource, final String contigID, final long length, final int bufferSize) { this.dataSource = dataSource; this.contigID = contigID; this.length = length; this.bufferSize = (int) Math.min(bufferSize , length); this.buffer = null; this.previousBuffer = null; this.bufferStart = -1; this.bufferEnd = -1; } public String contigID() { return contigID; } private void loadStartingAt(final long start) { final long maximumEnd = start + bufferSize - 1; final long newEnd = Math.min(maximumEnd, length); previousBuffer = buffer != null && bufferStart == start - buffer.length ? buffer : null; // only cache previous if it is contiguous. buffer = dataSource.queryAndPrefetch(contigID, start, newEnd).getBases(); bufferStart = start; bufferEnd = newEnd; } public static BufferedReferenceBases of(final ReferenceDataSource dataSource, final String contigId, final int bufferSize) { Utils.nonNull(dataSource); Utils.nonNull(contigId); ParamUtils.isPositive(bufferSize, "buffer size"); final SAMSequenceRecord sequenceRecord = dataSource.getSequenceDictionary().getSequence(contigId); if (sequenceRecord == null) { throw new IllegalArgumentException("there is not such sequence/contig id " + contigId + " in input data-source"); } return new BufferedReferenceBases(dataSource, contigId, sequenceRecord.getSequenceLength(), bufferSize); } public long length() { return length; } final int copyBytesAt(final long position, final byte[] dest, final int offset, final int requestLength) { final long lastPosition = Math.min(length, position + requestLength - 1); long p; int o; for (p = position, o = offset; p <= lastPosition; ++p, ++o) { dest[o] = byteAt(p); } return (int) (lastPosition - position + 1); } byte byteAt(final long location) { if (location < bufferStart) { if (location < 0) { throw new IllegalArgumentException("invalid location outside range: " + location); } else if (previousBuffer != null && location >= bufferStart - previousBuffer.length) { return previousBuffer[(int) (location - (bufferStart - previousBuffer.length))]; } else { loadStartingAt(location); return buffer[0]; } } else if (location > bufferEnd) { if (location > length) { throw new IllegalArgumentException("invalid location"); } else { loadStartingAt(location); return buffer[0]; } } else { return buffer[(int) (location - bufferStart)]; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy