/* * Copyright (c) 2014. Real Time Genomics Limited. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT * HOLDER OR 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. */ package com.rtg.reader; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.UUID; import com.rtg.mode.Protein; import com.rtg.util.diagnostic.NoTalkbackSlimException; import com.rtg.util.integrity.Exam; import com.rtg.util.integrity.Integrity; import com.rtg.util.io.FileUtils; /** * Handles reading and writing the main index file for preread */ public class IndexFile implements Integrity { static final long VERSION = 13L; /** The version at which we started to calculate a global checksum */ public static final long SINGLE_CHECKSUM_VERSION = 2L; //version in which quality data was added private static final long QUALITY_VERSION = 3L; //version in which histogram was added static final long N_HISTOGRAM_AND_SDF_TYPE_VERSION = 4L; private static final long DOUBLE_HASH_FIX_VERSION = 5L; private static final long PARAMETER_STORING_VERSION = 6L; /** The version at which we switched from global checksum to separate checksums for data/qualities/names */ public static final long SEPARATE_CHECKSUM_VERSION = 7L; private static final long WORKING_DIR_AND_ENCODINGS_VERSION = 8L; private static final long DATASIZE_IN_DATA_INDICES_VERSION = 9L; /** The version we switched SDF-ID from a random long to a UUID */ private static final long UUID_VERSION = 10L; /** The version we added the per sequence checksum files */ static final long PER_SEQUENCE_CHECKSUM_VERSION = 11L; /** the version we added full sequence name storage */ static final long FULL_SEQUENCE_NAME_VERSION = 12L; /** the version we added sam read group */ static final long SAM_READ_GROUP_VERSION = 13L; /** Normal name encoding constant */ public static final byte NAME_ENCODING_NORMAL = 0; /** Normal sequence encoding constant */ public static final byte SEQUENCE_ENCODING_NORMAL = 0; /** Normal quality encoding constant */ public static final byte QUALITY_ENCODING_NORMAL = 0; /** Compressed sequence encoding constant, using BitwiseByteArray */ public static final byte SEQUENCE_ENCODING_COMPRESSED = 1; /** Compressed quality encoding constant, using CompressedByteArray */ public static final byte QUALITY_ENCODING_COMPRESSED = 1; private long mSeqIndexVersion; private long mMaxFilesize; private int mSequenceType; private long mTotalLength; private long mMaxLength; private long mMinLength; private long mNumberSequences; private long mVersion; private long[] mResidueCount; private long[] mNHistogram; private long[] mPosHistogram; private double mGlobalQSAverage; private double[] mPositionAverageHistogram; private long mLongestNBlock; private long mNBlocksCount; private long mSdfIdLowBits; //only to be used in constructor for loading private long mDataChecksum; private long mQualityChecksum; private long mNameChecksum; private long mNameSuffixChecksum; private boolean mHasQuality; private PrereadType mPrereadType; private PrereadArm mPrereadArm; private String mCommandLine; private String mComment; private String mSamReadGroup = null; private byte mNameEncoding; private byte mSequenceEncoding; private byte mQualityEncoding; private static final int NUMBER_SEQUENCE_ENCODINGS = 1; private static final int NUMBER_QUALITY_ENCODINGS = 1; private boolean mHasNames = true; private boolean mHasSuffixes; //private UUID mSdfUuid; private SdfId mSdfId; /** * Constructs object, reading in all values from index * @param dir Directory containing Preread index * @throws IOException If an I/O error occurs */ public IndexFile(final File dir) throws IOException { mPrereadArm = PrereadArm.UNKNOWN; mPrereadType = PrereadType.UNKNOWN; mSdfId = new SdfId(0); final File index = new File(dir, SdfFileUtils.INDEX_FILENAME); try (DataInputStream indexStream = new DataInputStream(new BufferedInputStream(new FileInputStream(index), FileUtils.BUFFERED_STREAM_SIZE))) { final PrereadHashFunction headerHash = new PrereadHashFunction(); version1Load(indexStream, headerHash, dir); if (mVersion > VERSION) { throw new NoTalkbackSlimException("The SDF " + dir + " has been created with a newer version of RTG tools and cannot be read with this version."); } loadVersion3Fields(indexStream, headerHash); loadVersion4Fields(indexStream, headerHash, dir); loadVersion6Fields(indexStream, headerHash); loadVersion8Fields(indexStream, headerHash); loadVersion9Fields(); loadVersion10Fields(indexStream, headerHash); loadVersion12Fields(indexStream, headerHash); loadVersion13Fields(indexStream, headerHash); checksumLoad(indexStream, headerHash, dir); } catch (final EOFException e) { throw new CorruptSdfException(dir); } } private void checksumLoad(DataInputStream indexStream, PrereadHashFunction headerHash, File dir) throws IOException { if (mVersion >= SINGLE_CHECKSUM_VERSION) { mDataChecksum = indexStream.readLong(); headerHash.irvineHash(mDataChecksum); if (mVersion >= SEPARATE_CHECKSUM_VERSION) { mQualityChecksum = indexStream.readLong(); headerHash.irvineHash(mQualityChecksum); mNameChecksum = indexStream.readLong(); headerHash.irvineHash(mNameChecksum); } if (mVersion >= FULL_SEQUENCE_NAME_VERSION) { mNameSuffixChecksum = indexStream.readLong(); headerHash.irvineHash(mNameSuffixChecksum); } final long original = indexStream.readLong(); if (headerHash.getHash() != original) { throw new CorruptSdfException(dir); } } } //Initial version fields private void version1Load(DataInputStream indexStream, PrereadHashFunction headerHash, File dir) throws IOException { mVersion = indexStream.readLong(); headerHash.irvineHash(mVersion); mMaxFilesize = indexStream.readLong(); headerHash.irvineHash(mMaxFilesize); mSequenceType = indexStream.readInt(); headerHash.irvineHash((long) mSequenceType); mMaxLength = indexStream.readLong(); headerHash.irvineHash(mMaxLength); mMinLength = indexStream.readLong(); headerHash.irvineHash(mMinLength); mTotalLength = indexStream.readLong(); headerHash.irvineHash(mTotalLength); mNumberSequences = indexStream.readLong(); headerHash.irvineHash(mNumberSequences); final int totalResidue = indexStream.readInt(); headerHash.irvineHash((long) totalResidue); // Safety check to prevent possible OOM error on next allocation if (totalResidue > Protein.values().length || totalResidue < 0) { throw new CorruptSdfException(dir); } mResidueCount = new long[totalResidue]; long count = 0; for (int i = 0; i < totalResidue; ++i) { mResidueCount[i] = indexStream.readLong(); headerHash.irvineHash(mResidueCount[i]); count += mResidueCount[i]; } if (count != mTotalLength) { throw new CorruptSdfException(dir); } } //quality data fields private void loadVersion3Fields(DataInputStream indexStream, PrereadHashFunction headerHash) throws IOException { if (mVersion >= QUALITY_VERSION) { final int qualityByte = indexStream.read(); headerHash.irvineHash(qualityByte); mHasQuality = qualityByte != 0; } else { mHasQuality = false; } } //type and histogram fields/data private void loadVersion4Fields(DataInputStream indexStream, PrereadHashFunction headerHash, File dir) throws IOException { if (mVersion >= N_HISTOGRAM_AND_SDF_TYPE_VERSION) { mNBlocksCount = indexStream.readLong(); headerHash.irvineHash(mNBlocksCount); mLongestNBlock = indexStream.readLong(); headerHash.irvineHash(mLongestNBlock); //read N histogram mNHistogram = new long[SdfWriter.MAX_HISTOGRAM]; for (int i = 0; i < mNHistogram.length; ++i) { mNHistogram[i] = indexStream.readLong(); headerHash.irvineHash(mNHistogram[i]); } //read Pos histogram mPosHistogram = new long[SdfWriter.MAX_HISTOGRAM]; for (int i = 0; i < mPosHistogram.length; ++i) { mPosHistogram[i] = indexStream.readLong(); headerHash.irvineHash(mPosHistogram[i]); } //read QS average histogram mGlobalQSAverage = indexStream.readDouble(); compatDoubleHash(headerHash, mVersion, mGlobalQSAverage); //headerHash.irvineHash(String.valueOf(mGlobalQSAverage)); mPositionAverageHistogram = new double[SdfWriter.MAX_HISTOGRAM]; for (int i = 0; i < mPositionAverageHistogram.length; ++i) { mPositionAverageHistogram[i] = indexStream.readDouble(); compatDoubleHash(headerHash, mVersion, mPositionAverageHistogram[i]); //headerHash.irvineHash(String.valueOf(mPositionAverageHistogram[i])); } //read sdf type final int prereadArm = indexStream.readInt(); if (prereadArm > PrereadArm.values().length || prereadArm < 0) { throw new CorruptSdfException(dir); } mPrereadArm = PrereadArm.values()[prereadArm]; headerHash.irvineHash((long) mPrereadArm.ordinal()); final int prereadType = indexStream.readInt(); if (prereadType > PrereadType.values().length || prereadType < 0) { throw new CorruptSdfException(dir); } mPrereadType = PrereadType.values()[prereadType]; headerHash.irvineHash((long) mPrereadType.ordinal()); mSdfIdLowBits = indexStream.readLong(); headerHash.irvineHash(mSdfIdLowBits); } } //command line field private void loadVersion6Fields(DataInputStream indexStream, PrereadHashFunction headerHash) throws IOException { if (mVersion >= PARAMETER_STORING_VERSION) { mCommandLine = readText(indexStream, headerHash); mComment = readText(indexStream, headerHash); } else { mCommandLine = null; mComment = null; } } private void loadVersion8Fields(DataInputStream indexStream, PrereadHashFunction headerHash) throws IOException { if (mVersion >= WORKING_DIR_AND_ENCODINGS_VERSION) { readText(indexStream, headerHash); headerHash.irvineHash(indexStream.readLong()); mNameEncoding = (byte) indexStream.read(); headerHash.irvineHash((int) mNameEncoding); mSequenceEncoding = (byte) indexStream.read(); headerHash.irvineHash((int) mSequenceEncoding); mQualityEncoding = (byte) indexStream.read(); headerHash.irvineHash((int) mQualityEncoding); final int nameByte = indexStream.read(); headerHash.irvineHash(nameByte); mHasNames = nameByte != 0; } else { mNameEncoding = NAME_ENCODING_NORMAL; mSequenceEncoding = SEQUENCE_ENCODING_NORMAL; mQualityEncoding = QUALITY_ENCODING_NORMAL; mHasNames = true; } } private void loadVersion9Fields() { if (mVersion >= DATASIZE_IN_DATA_INDICES_VERSION) { mSeqIndexVersion = DataFileIndex.DATASIZE_VERSION; } else { mSeqIndexVersion = DataFileIndex.SEQ_COUNT_ONLY_VERSION; } } private void loadVersion10Fields(DataInputStream indexStream, PrereadHashFunction headerHash) throws IOException { if (mVersion >= UUID_VERSION) { final long sdfIdHighBits = indexStream.readLong(); headerHash.irvineHash(sdfIdHighBits); mSdfId = new SdfId(new UUID(sdfIdHighBits, mSdfIdLowBits)); } else { mSdfId = new SdfId(mSdfIdLowBits); } } private void loadVersion12Fields(DataInputStream indexStream, PrereadHashFunction headerHash) throws IOException { if (mVersion >= FULL_SEQUENCE_NAME_VERSION) { final int hasSuffixesByte = indexStream.read(); headerHash.irvineHash(hasSuffixesByte); mHasSuffixes = hasSuffixesByte != 0; } else { mHasSuffixes = false; } } private void loadVersion13Fields(DataInputStream indexStream, PrereadHashFunction headerHash) throws IOException { if (mVersion >= SAM_READ_GROUP_VERSION) { mSamReadGroup = readText(indexStream, headerHash); } else { mSamReadGroup = null; } } private static String readText(final DataInputStream inputStream, final PrereadHashFunction headerHash) throws IOException { final int len = inputStream.readInt(); headerHash.irvineHash(len); if (len == 0) { return ""; } else if (len < 0) { throw new CorruptSdfException(); } else { final byte[] bs = new byte[len]; inputStream.readFully(bs); final String s = new String(bs); headerHash.irvineHash(s); return s; } } /** * Constructs object from parameters * @param maxFilesize value * @param sequenceType value * @param totalLength value * @param maxLength value * @param minLength value * @param numberSequences value */ public IndexFile(final long maxFilesize, final int sequenceType, final long totalLength, final long maxLength, final long minLength, final long numberSequences) { mMaxFilesize = maxFilesize; mSequenceType = sequenceType; mTotalLength = totalLength; mMaxLength = maxLength; mMinLength = minLength; mNumberSequences = numberSequences; mPrereadArm = PrereadArm.UNKNOWN; mPrereadType = PrereadType.UNKNOWN; mSdfIdLowBits = 0; mSdfId = new SdfId(0); mSeqIndexVersion = DataFileIndex.DATASIZE_VERSION; mVersion = VERSION; } /** * @return maximum allowed file size */ public long getMaxFileSize() { return mMaxFilesize; } /** * @return ordinal of sequence type */ public int getSequenceType() { return mSequenceType; } /** * @return total length of all sequences */ public long getTotalLength() { return mTotalLength; } /** * @return highest length among sequences */ public long getMaxLength() { return mMaxLength; } /** * @return smallest length among sequences */ public long getMinLength() { return mMinLength; } /** * @return total number of sequences */ public long getNumberSequences() { return mNumberSequences; } /** * @return Returns version of saved data */ public long getVersion() { return mVersion; } /** * Sets the residue count array * @param countArray array containing residue counts */ void setResidueCounts(final long[] countArray) { mResidueCount = countArray; } /** * Sets the N Histogram * @param histogram array containing values */ void setNHistogram(final long[] histogram) { mNHistogram = histogram; } /** * Sets the Position Histogram (counts Ns per position in read) * @param histogram array containing values */ void setPosHistogram(final long[] histogram) { mPosHistogram = histogram; } void setLongestNBlock(final long val) { mLongestNBlock = val; } void setNBlocksCount(final long val) { mNBlocksCount = val; } void setGlobalQSAverage(final double average) { mGlobalQSAverage = average; } void setHasQuality(final boolean has) { mHasQuality = has; } /** * Whether the pre-read has quality data * @return true if the SDF has quality values */ public boolean hasQuality() { return mHasQuality; } void setHasNames(boolean v) { mHasNames = v; } void setHasSuffixes(boolean v) { mHasSuffixes = v; } /** * Whether SDF has names for sequences stored or not * @return true if the SDF sequences have names */ public boolean hasNames() { return mHasNames; } void setCommandLine(final String params) { mCommandLine = params; } /** * The command line parameters used to generated this SDF * @return the command line parameters */ public String getCommandLine() { if (mCommandLine == null || mCommandLine.isEmpty()) { return null; } return mCommandLine; } void setComment(final String comment) { mComment = comment; } /** * A comment for this SDF * @return the comment text */ public String getComment() { if (mComment == null || mComment.isEmpty()) { return null; } return mComment; } void setSamReadGroup(final String samReadGroup) { mSamReadGroup = samReadGroup; } /** * A comment for this SDF * @return the comment text */ public String getSamReadGroup() { if (mSamReadGroup == null || mSamReadGroup.isEmpty()) { return null; } return mSamReadGroup; } /** * Return the residue counts * @return residue counts array */ long[] getResidueCounts() { return mResidueCount; } /** * Return the histogram of Ns per sequence * @return array containing histogram */ long[] getNHistogram() { return mNHistogram; } /** * Return the histogram of Ns per position in sequence * @return array containing histogram */ long[] getPosHistogram() { return mPosHistogram; } /** * Return the global QS average * @return global QS average */ double getQSAverage() { return mGlobalQSAverage; } long getLongestNBlock() { return mLongestNBlock; } long getNBlockCount() { return mNBlocksCount; } /** * Tell if we have a N statistics (histogram, blocks and longest block) * @return true if N statistics are available */ boolean hasNStats() { return mVersion >= N_HISTOGRAM_AND_SDF_TYPE_VERSION; } /** * @param dir Saves index into supplied directory * @throws IOException If an I/O error occurs */ public void save(final File dir) throws IOException { final File index = new File(dir, SdfFileUtils.INDEX_FILENAME); try (DataOutputStream indexStream = new DataOutputStream(new FileOutputStream(index))) { if (mResidueCount == null) { throw new IllegalStateException("Residue count cannot be null"); } final PrereadHashFunction headerHash = new PrereadHashFunction(); indexStream.writeLong(VERSION); //8 headerHash.irvineHash(VERSION); indexStream.writeLong(mMaxFilesize); //16 headerHash.irvineHash(mMaxFilesize); indexStream.writeInt(mSequenceType); //20 headerHash.irvineHash((long) mSequenceType); indexStream.writeLong(mMaxLength); //28 headerHash.irvineHash(mMaxLength); indexStream.writeLong(mMinLength); //36 headerHash.irvineHash(mMinLength); indexStream.writeLong(mTotalLength); //44 headerHash.irvineHash(mTotalLength); indexStream.writeLong(mNumberSequences); //52 headerHash.irvineHash(mNumberSequences); indexStream.writeInt(mResidueCount.length); //56 headerHash.irvineHash((long) mResidueCount.length); for (final long count : mResidueCount) { indexStream.writeLong(count); //96 for DNA, 232 for Protein headerHash.irvineHash(count); } final int qualityByte = mHasQuality ? 1 : 0; indexStream.writeByte(qualityByte); //97/233 headerHash.irvineHash(qualityByte); //write histogram indexStream.writeLong(mNBlocksCount); headerHash.irvineHash(mNBlocksCount); indexStream.writeLong(mLongestNBlock); headerHash.irvineHash(mLongestNBlock); for (final long h : mNHistogram) { indexStream.writeLong(h); headerHash.irvineHash(h); } for (final long h : mPosHistogram) { indexStream.writeLong(h); headerHash.irvineHash(h); } indexStream.writeDouble(mGlobalQSAverage); compatDoubleHash(headerHash, VERSION, mGlobalQSAverage); //headerHash.irvineHash(String.valueOf(mGlobalQSAverage)); for (final double h : mPositionAverageHistogram) { indexStream.writeDouble(h); compatDoubleHash(headerHash, VERSION, h); //headerHash.irvineHash(String.valueOf(mPositionAverageHistogram[i])); } //write sdf type indexStream.writeInt(mPrereadArm.ordinal()); headerHash.irvineHash((long) mPrereadArm.ordinal()); indexStream.writeInt(mPrereadType.ordinal()); headerHash.irvineHash((long) mPrereadType.ordinal()); indexStream.writeLong(mSdfId.getLowBits()); headerHash.irvineHash(mSdfId.getLowBits()); // V6 writeText(mCommandLine, indexStream, headerHash); writeText(mComment, indexStream, headerHash); // V8 writeText(System.getProperty("user.dir"), indexStream, headerHash); final long time = System.currentTimeMillis(); indexStream.writeLong(time); headerHash.irvineHash(time); indexStream.writeByte(mNameEncoding); headerHash.irvineHash(mNameEncoding); indexStream.writeByte(mSequenceEncoding); headerHash.irvineHash(mSequenceEncoding); indexStream.writeByte(mQualityEncoding); headerHash.irvineHash(mQualityEncoding); final int nameByte = mHasNames ? 1 : 0; indexStream.writeByte(nameByte); headerHash.irvineHash(nameByte); // V10 indexStream.writeLong(mSdfId.getHighBits()); headerHash.irvineHash(mSdfId.getHighBits()); // V12 final int suffixByte = mHasSuffixes ? 1 : 0; indexStream.writeByte(suffixByte); headerHash.irvineHash(suffixByte); // V13 writeText(mSamReadGroup, indexStream, headerHash); // Finishing checksums indexStream.writeLong(mDataChecksum); headerHash.irvineHash(mDataChecksum); indexStream.writeLong(mQualityChecksum); headerHash.irvineHash(mQualityChecksum); indexStream.writeLong(mNameChecksum); headerHash.irvineHash(mNameChecksum); indexStream.writeLong(mNameSuffixChecksum); headerHash.irvineHash(mNameSuffixChecksum); indexStream.writeLong(headerHash.getHash()); } } private static void writeText(final String text, final DataOutputStream dos, final PrereadHashFunction headerHash) throws IOException { if (text == null) { dos.writeInt(0); headerHash.irvineHash(0); return; } final byte[] bs = text.getBytes(); dos.writeInt(bs.length); headerHash.irvineHash(bs.length); if (bs.length > 0) { dos.write(bs); headerHash.irvineHash(text); } } @Override public boolean globalIntegrity() { integrity(); return true; } @Override public boolean integrity() { Exam.assertTrue(mTotalLength >= mMaxLength); Exam.assertTrue(mMaxLength >= mMinLength); Exam.assertTrue(mMinLength > 0 || (mMinLength == 0 && mNumberSequences == 0)); Exam.assertTrue(mNumberSequences >= 0); return true; } byte getNameEncoding() { return mNameEncoding; } void setSequenceEncoding(byte val) { if (val < 0 || val > NUMBER_SEQUENCE_ENCODINGS) { throw new IllegalArgumentException("val=" + val); } mSequenceEncoding = val; } byte getSequenceEncoding() { return mSequenceEncoding; } void setQualityEncoding(byte val) { if (val < 0 || val > NUMBER_QUALITY_ENCODINGS) { throw new IllegalArgumentException("val=" + val); } mQualityEncoding = val; } byte getQualityEncoding() { return mQualityEncoding; } /** * Set the checksum on data values * @param hash the data checksum */ public final void setDataChecksum(final long hash) { mDataChecksum = hash; } /** * @return the data checksum */ public final long getDataChecksum() { return mDataChecksum; } /** * Set the checksum on quality values * @param hash the quality checksum */ public final void setQualityChecksum(final long hash) { mQualityChecksum = hash; } /** * @return the quality checksum */ public final long getQualityChecksum() { return mQualityChecksum; } /** * Set the checksum on sequence names * @param hash the name checksum */ public final void setNameChecksum(final long hash) { mNameChecksum = hash; } /** * Set the checksum on sequence name suffixes * @param hash the name checksum */ public final void setNameSuffixChecksum(final long hash) { mNameSuffixChecksum = hash; } /** * @return the name checksum */ public final long getNameChecksum() { return mNameChecksum; } /** * @return the name suffix checksum */ public final long getNameSuffixChecksum() { return mNameSuffixChecksum; } /** * @return the preread arm for sequences in this SDF */ public final PrereadArm getPrereadArm() { return mPrereadArm; } /** * @return version of data index files */ public long dataIndexVersion() { return mSeqIndexVersion; } /** * Set the preread arm * @param arm preread arm */ public final void setPrereadArm(final PrereadArm arm) { mPrereadArm = arm; } /** * @return preread type */ public final PrereadType getPrereadType() { return mPrereadType; } /** * Gets the preread type from a format * @param desc input format * @return the preread type */ public static PrereadType typeFromFormat(DataSourceDescription desc) { if (desc.isCompleteGenomics()) { return PrereadType.CG; } if (desc.getQualityFormat() == QualityFormat.SOLEXA || desc.getQualityFormat() == QualityFormat.SOLEXA1_3) { return PrereadType.SOLEXA; } return PrereadType.UNKNOWN; } /** * Set the preread type * @param type the type */ public final void setPrereadType(final PrereadType type) { mPrereadType = type; } /** * Sets the id * @param id id of this SDF */ public void setSdfId(final SdfId id) { mSdfId = id; } /** * @return the id of this SDF */ public SdfId getSdfId() { return mSdfId; } /** * @return true if SDF has per sequence checksums */ boolean hasPerSequenceChecksums() { return mVersion >= PER_SEQUENCE_CHECKSUM_VERSION; } /** * @return whether we have a separate file for full sequence names */ public boolean hasSequenceNameSuffixes() { return mHasSuffixes && hasNames(); } void setQSPostionAverageHistogram(final double[] posAverages) { mPositionAverageHistogram = posAverages.clone(); } /** * @return the histogram of average quality scores */ public double[] getQSPositionAverageHistogram() { return mPositionAverageHistogram.clone(); } private void compatDoubleHash(final PrereadHashFunction hash, final long version, final double val) { if (version >= DOUBLE_HASH_FIX_VERSION) { hash.irvineHash(Double.doubleToLongBits(val)); } else { hash.irvineHash(String.valueOf(val)); } } }