diff --git a/.travis.yml b/.travis.yml index a1c1b2bcfb..45bc976612 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,20 @@ cache: jdk: - oraclejdk8 - openjdk8 -script: ./gradlew test jacocoTestReport; +matrix: + fast_finish: true + allow_failures: + - env: TEST_TYPE=FTP + include: + - jdk: oraclejdk8 + env: TEST_TYPE=FTP +script: + - if [[ $TEST_TYPE == "FTP" ]]; then + ./gradlew testFTP jacocoTestReport; + else + ./gradlew test jacocoTestReport; + fi + after_success: - bash <(curl -s https://codecov.io/bash) - echo "TRAVIS_BRANCH='$TRAVIS_BRANCH'"; diff --git a/build.gradle b/build.gradle index 2cffacb19a..25a8e7d07c 100644 --- a/build.gradle +++ b/build.gradle @@ -10,9 +10,9 @@ plugins { id 'maven' id 'signing' id 'jacoco' - id 'com.palantir.git-version' version '0.5.1' - id 'com.github.johnrengelman.shadow' version '1.2.3' - id 'com.github.maiflai.scalatest' version '0.15' + id 'com.palantir.git-version' version '0.11.0' + id 'com.github.johnrengelman.shadow' version '2.0.4' + id 'com.github.maiflai.scalatest' version '0.22' } repositories { @@ -36,13 +36,14 @@ dependencies { compile "org.xerial.snappy:snappy-java:1.1.4" compile "org.apache.commons:commons-compress:1.4.1" compile "org.tukaani:xz:1.5" - compile "gov.nih.nlm.ncbi:ngs-java:1.2.4" + compile "gov.nih.nlm.ncbi:ngs-java:2.9.0" - testCompile "org.scala-lang:scala-library:2.12.1" - testCompile "org.scalatest:scalatest_2.12:3.0.1" - testRuntime 'org.pegdown:pegdown:1.4.2' // Necessary for generating HTML reports with ScalaTest - testCompile "org.testng:testng:6.9.9" + testCompile "org.scala-lang:scala-library:2.12.6" + testCompile "org.scalatest:scalatest_2.12:3.0.5" + testRuntime 'org.pegdown:pegdown:1.6.0' // Necessary for generating HTML reports with ScalaTest + testCompile "org.testng:testng:6.14.3" testCompile "com.google.jimfs:jimfs:1.1" + testCompile "com.google.guava:guava:26.0-jre" } sourceCompatibility = 1.8 @@ -100,11 +101,22 @@ test { tags { exclude "slow" exclude "broken" + exclude "ftp" if (System.env.CI == "false") exclude "sra" if (!OperatingSystem.current().isUnix()) exclude "unix" } } dependsOn findScalaAndJavaTypes + +task testFTP(type: Test) { + description = "Runs the tests that require connection to a remote ftp server" + tags { + include "ftp" + exclude "slow" + exclude "broken" + } +} + task testSRA(type: Test) { description = "Run the SRA tests" jvmArgs += '-Dsamjdk.sra_libraries_download=true' @@ -115,9 +127,8 @@ task testSRA(type: Test) { } } -task wrapper(type: Wrapper) { - description = "Regenerate the gradle wrapper" - gradleVersion = '3.2.1' +wrapper { + gradleVersion = '4.8.1' } // This is a hack to disable the java 8 default javadoc lint until we fix the html formatting diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 6ffa237849..758de960ec 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f08cd01bf2..2d80b69a76 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Fri Jan 20 17:10:11 EST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-all.zip diff --git a/gradlew b/gradlew index 9aa616c273..cccdd3d517 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS="" # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -154,16 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then cd "$(dirname "$0")" fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/src/main/java/htsjdk/samtools/AbstractSAMHeaderRecord.java b/src/main/java/htsjdk/samtools/AbstractSAMHeaderRecord.java index 0c3d484203..d62bf5c62d 100644 --- a/src/main/java/htsjdk/samtools/AbstractSAMHeaderRecord.java +++ b/src/main/java/htsjdk/samtools/AbstractSAMHeaderRecord.java @@ -23,7 +23,7 @@ */ package htsjdk.samtools; -import javax.xml.bind.annotation.XmlTransient; + import java.io.Serializable; import java.util.LinkedHashMap; import java.util.Map; @@ -33,7 +33,7 @@ * Base class for the various concrete records in a SAM header, providing uniform * access to the attributes. */ -@XmlTransient /* don't consider this class for XML-serialization */ + public abstract class AbstractSAMHeaderRecord implements Serializable { public static final long serialVersionUID = 1L; diff --git a/src/main/java/htsjdk/samtools/BAMFileWriter.java b/src/main/java/htsjdk/samtools/BAMFileWriter.java index 95a26b42f7..3aee3898d7 100644 --- a/src/main/java/htsjdk/samtools/BAMFileWriter.java +++ b/src/main/java/htsjdk/samtools/BAMFileWriter.java @@ -40,7 +40,7 @@ /** * Concrete implementation of SAMFileWriter for writing gzipped BAM files. */ -class BAMFileWriter extends SAMFileWriterImpl { +public class BAMFileWriter extends SAMFileWriterImpl { private final BinaryCodec outputBinaryCodec; private BAMRecordCodec bamRecordCodec = null; @@ -78,7 +78,7 @@ protected BAMFileWriter(final OutputStream os, final File file, final int compre } protected BAMFileWriter(final OutputStream os, final String absoluteFilename, final int compressionLevel, final DeflaterFactory deflaterFactory) { - blockCompressedOutputStream = new BlockCompressedOutputStream(os, null, compressionLevel, deflaterFactory); + blockCompressedOutputStream = new BlockCompressedOutputStream(os, (Path)null, compressionLevel, deflaterFactory); outputBinaryCodec = new BinaryCodec(blockCompressedOutputStream); outputBinaryCodec.setOutputFileName(absoluteFilename); } @@ -200,8 +200,13 @@ protected static void writeHeader(final BinaryCodec outputBinaryCodec, final SAM writeHeader(outputBinaryCodec, samFileHeader, headerString); } - protected static void writeHeader(final OutputStream outputStream, final SAMFileHeader samFileHeader) { - final BlockCompressedOutputStream blockCompressedOutputStream = new BlockCompressedOutputStream(outputStream, null); + /** + * Write a BAM file header to an output stream in block compressed BAM format. + * @param outputStream the stream to write the BAM header to + * @param samFileHeader the header to write + */ + public static void writeHeader(final OutputStream outputStream, final SAMFileHeader samFileHeader) { + final BlockCompressedOutputStream blockCompressedOutputStream = new BlockCompressedOutputStream(outputStream, (Path)null); final BinaryCodec outputBinaryCodec = new BinaryCodec(blockCompressedOutputStream); writeHeader(outputBinaryCodec, samFileHeader); try { diff --git a/src/main/java/htsjdk/samtools/BAMRecord.java b/src/main/java/htsjdk/samtools/BAMRecord.java index 14b6295954..5374b18400 100644 --- a/src/main/java/htsjdk/samtools/BAMRecord.java +++ b/src/main/java/htsjdk/samtools/BAMRecord.java @@ -28,6 +28,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; +import static htsjdk.samtools.SAMTag.CG; /** * Wrapper class for binary BAM records. @@ -39,6 +40,28 @@ public class BAMRecord extends SAMRecord { */ private static final int READ_NAME_OFFSET = 0; + /** + * Constant for converting between the number of operators in a Cigar and the length + * of the int[] array needed to represent it in the BAM format + */ + static public final short CIGAR_SIZE_MULTIPLIER = 4; + + /** + * Maximal number of cigar operators that can be represented normally in the cigar part of the bam record. + * Records that have larger cigars will have their Cigars encoded to int[] and placed in the CG tag in the attributes (BAM only) + * This should happen upon encoding. In place of the Cigar a sentinel value will be placed SN + *

+ * When a BAM record is decoded, the sentinel cigar informs of the existance of the CG tag, which is decoded and removed. + * The sentinel value is then replaced with the actual cigar (in memory). + */ + public final static int MAX_CIGAR_OPERATORS = 0xffff; + + public final static int MAX_CIGAR_ELEMENT_LENGTH = (1 << 28) - 1; + /** + * Number of operators in "Sentinel" cigar xSyN + */ + private final static int LONG_CIGAR_SENTINEL_LENGTH = 2; + /** * Variable-length part of BAMRecord. Lazily decoded. */ @@ -203,6 +226,12 @@ protected void setAttribute(final short tag, final Object value, final boolean i */ @Override public void clearAttributes() { + // If there's a long cigar, the CG might be "hiding" in the attributes, and + // if the original attributes haven't been parsed yet, we will lose the long cigar. + // by "getting" the cigar prior to clearing the attributes, we protect against that. + if (!mAttributesDecoded) { + getCigar(); + } mAttributesDecoded = true; mBinaryDataStale = true; super.clearAttributes(); @@ -244,10 +273,15 @@ public int getReadNameLength() { public Cigar getCigar() { if (mRestOfBinaryData != null && !mCigarDecoded) { final int cigarOffset = readNameSize(); - final ByteBuffer byteBuffer = ByteBuffer.wrap(mRestOfBinaryData, cigarOffset, cigarSize()); + final ByteBuffer byteBuffer = ByteBuffer.wrap(mRestOfBinaryData, cigarOffset, cigarSize()); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); super.initializeCigar(BinaryCigarCodec.decode(byteBuffer)); mCigarDecoded = true; + + if (getCigarLength() == LONG_CIGAR_SENTINEL_LENGTH && isSentinelCigar(super.getCigar(), getReadLength())) { + extractCigarFromCGAttribute(super.getCigar()); + } + if (null != getHeader() && getValidationStringency() != ValidationStringency.SILENT && !this.getReadUnmappedFlag()) { // Don't know line number, and don't want to force read name to be decoded. SAMUtils.processValidationErrors(validateCigar(-1L), -1, getValidationStringency()); @@ -256,6 +290,72 @@ public Cigar getCigar() { return super.getCigar(); } + /** + * Checks to see if the provided Cigar could be considered the "sentinel cigar" that indicates + * that the actual cigar is too long for the BAM spec and should be taken from the CG tag. This + * was introduced in SAM v1.6. + */ + static boolean isSentinelCigar(final Cigar cigar, final int readLength) { + // There's an implicit assumption here there readLength == length of read in cigar, unless readLength==0 + return cigar.numCigarElements() == 2 && + cigar.getCigarElement(1).getOperator() == CigarOperator.N && + cigar.getCigarElement(0).getOperator() == CigarOperator.S && + (cigar.getCigarElement(0).getLength() == readLength || readLength == 0) ; + } + + + /** + * Long cigars (with more than 64K operators) cannot be encoded into BAM. Instead a sentinel cigar is + * placed as a placeholder, and the actual cigar is placed in the CG tag. This method + * extracts the CIGAR from the CG tag and places it into the (in memory) cigar. + */ + private void extractCigarFromCGAttribute(final Cigar sentinelCigar) throws IllegalStateException { + final int[] cigarFromCG = (int[]) getAttribute(SAMTagUtil.getSingleton().CG); + + if (cigarFromCG == null) return; + + // place the integer array into a buffer so we can decode it + final ByteBuffer byteBuffer = ByteBuffer.allocate(cigarFromCG.length * CIGAR_SIZE_MULTIPLIER) + .order(ByteOrder.LITTLE_ENDIAN); + byteBuffer.asIntBuffer().put(cigarFromCG); + + // decode cigar + final Cigar decodedCigar = BinaryCigarCodec.decode(byteBuffer); + + // Sanity check + if (decodedCigar.numCigarElements() <= MAX_CIGAR_OPERATORS) { + throw new IllegalStateException(String.format( + "Only Cigar with > %d operators should be placed in CG tag. Found %d operators. \n Here's the Cigar:\n%s", + MAX_CIGAR_OPERATORS, + decodedCigar.getCigarElements().size(), + decodedCigar.toString())); + } + + if (decodedCigar.getReferenceLength() != sentinelCigar.getReferenceLength()) { + throw new IllegalStateException(String.format( + "Sentinel cigar and %s cigar should have the same reference length. Found %d and %d.\n Here's the Cigar:\n%s", + CG.name(), + sentinelCigar.getReferenceLength(), + decodedCigar.getReferenceLength(), + decodedCigar.toString())); + } + + if (decodedCigar.getReadLength() != sentinelCigar.getReadLength() ) { + throw new IllegalStateException(String.format( + "Sentinel cigar and %s cigar should have the same read length. Found %d and %d.\n Here's the Cigar:\n%s", + CG.name(), + sentinelCigar.getReadLength(), + decodedCigar.getReadLength(), + decodedCigar.toString())); + } + + //used initializeCigar instead of setCigar so as to not clobber the indexingBin. + initializeCigar(decodedCigar); + + // remove CG attribute. + setAttribute(SAMTagUtil.getSingleton().CG, null); + } + /** * Avoids decoding CIGAR in order to get length. */ @@ -308,11 +408,17 @@ private void decodeAttributes() { if (mAttributesDecoded) { return; } + mAttributesDecoded = true; final int tagsOffset = readNameSize() + cigarSize() + basesSize() + qualsSize(); final int tagsSize = mRestOfBinaryData.length - tagsOffset; final SAMBinaryTagAndValue attributes = BinaryTagCodec.readTags(mRestOfBinaryData, tagsOffset, tagsSize, getValidationStringency()); setAttributes(attributes); + + // if there's a CG tag, we should getCigar() so that the CG tag has a chance of turning into the CIGAR + if (hasAttribute(CG.name())) { + getCigar(); + } } private byte[] decodeBaseQualities() { @@ -334,7 +440,7 @@ private byte[] decodeBaseQualities() { private String decodeReadName() { // Don't include terminating null - return StringUtil.bytesToString(mRestOfBinaryData, READ_NAME_OFFSET, mReadNameLength-1); + return StringUtil.bytesToString(mRestOfBinaryData, READ_NAME_OFFSET, mReadNameLength - 1); } private byte[] decodeReadBases() { @@ -344,7 +450,7 @@ private byte[] decodeReadBases() { final int basesOffset = readNameSize() + cigarSize(); try { return SAMUtils.compressedBasesToBytes(mReadLength, mRestOfBinaryData, basesOffset); - } catch ( final IllegalArgumentException ex ) { + } catch (final IllegalArgumentException ex) { final String msg = ex.getMessage() + " in read: " + getReadName(); throw new IllegalStateException(msg, ex); } @@ -358,11 +464,11 @@ private int readNameSize() { } private int cigarSize() { - return mCigarLength * 4; + return mCigarLength * CIGAR_SIZE_MULTIPLIER; } private int basesSize() { - return (mReadLength + 1)/2; + return (mReadLength + 1) / 2; } private int qualsSize() { diff --git a/src/main/java/htsjdk/samtools/BAMRecordCodec.java b/src/main/java/htsjdk/samtools/BAMRecordCodec.java index e363a5b95b..b269eaa9f5 100644 --- a/src/main/java/htsjdk/samtools/BAMRecordCodec.java +++ b/src/main/java/htsjdk/samtools/BAMRecordCodec.java @@ -24,6 +24,7 @@ package htsjdk.samtools; import htsjdk.samtools.util.BinaryCodec; +import htsjdk.samtools.util.Log; import htsjdk.samtools.util.RuntimeEOFException; import htsjdk.samtools.util.SortingCollection; @@ -31,15 +32,21 @@ import java.io.OutputStream; import java.util.Arrays; +import static htsjdk.samtools.SAMTag.CG; + /** * Class for translating between in-memory and disk representation of BAMRecord. */ public class BAMRecordCodec implements SortingCollection.Codec { + private final static Log LOG = Log.getInstance(BAMRecordCodec.class); + private final SAMFileHeader header; private final BinaryCodec binaryCodec = new BinaryCodec(); private final BinaryTagCodec binaryTagCodec = new BinaryTagCodec(binaryCodec); private final SAMRecordFactory samRecordFactory; + private boolean isReferenceSizeWarningShowed = false; + public BAMRecordCodec(final SAMFileHeader header) { this(header, new DefaultSAMRecordFactory()); } @@ -55,26 +62,33 @@ public BAMRecordCodec clone() { return new BAMRecordCodec(this.header, this.samRecordFactory); } - - /** Sets the output stream that records will be written to. */ + /** + * Sets the output stream that records will be written to. + */ @Override public void setOutputStream(final OutputStream os) { this.binaryCodec.setOutputStream(os); } - /** Sets the output stream that records will be written to. */ + /** + * Sets the output stream that records will be written to. + */ public void setOutputStream(final OutputStream os, final String filename) { this.binaryCodec.setOutputStream(os); this.binaryCodec.setOutputFileName(filename); } - /** Sets the input stream that records will be read from. */ + /** + * Sets the input stream that records will be read from. + */ @Override public void setInputStream(final InputStream is) { this.binaryCodec.setInputStream(is); } - /** Sets the input stream that records will be read from. */ + /** + * Sets the input stream that records will be read from. + */ public void setInputStream(final InputStream is, final String filename) { this.binaryCodec.setInputStream(is); this.binaryCodec.setInputFileName(filename); @@ -93,12 +107,21 @@ public void encode(final SAMRecord alignment) { // Compute block size, as it is the first element of the file representation of SAMRecord final int readLength = alignment.getReadLength(); + // if cigar is too long, put into CG tag and replace with sentinel value + if (alignment.getCigarLength() > BAMRecord.MAX_CIGAR_OPERATORS) { + + final int[] cigarEncoding = BinaryCigarCodec.encode(alignment.getCigar()); + alignment.setCigar(makeSentinelCigar(alignment.getCigar())); + alignment.setAttribute(CG.name(), cigarEncoding); + } + + // do not combine with previous call to alignment.getCigarLength() as cigar may change in-between final int cigarLength = alignment.getCigarLength(); - int blockSize = BAMFileConstants.FIXED_BLOCK_SIZE + alignment.getReadNameLength() + 1 + // null terminated - cigarLength * 4 + - (readLength + 1) / 2 + // 2 bases per byte, round up - readLength; + int blockSize = BAMFileConstants.FIXED_BLOCK_SIZE + alignment.getReadNameLength() + 1 + // null terminated + cigarLength * BAMRecord.CIGAR_SIZE_MULTIPLIER + + (readLength + 1) / 2 + // 2 bases per byte, round up + readLength; final int attributesSize = alignment.getAttributesBinarySize(); if (attributesSize != -1) { @@ -112,13 +135,12 @@ public void encode(final SAMRecord alignment) { } } + // shouldn't interact with the long-cigar above since the Sentinel Cigar has the same referenceLength as + // the actual cigar. int indexBin = 0; - if (alignment.getReferenceIndex() >= 0) { - if (alignment.getIndexingBin() != null) { - indexBin = alignment.getIndexingBin(); - } else { - indexBin = alignment.computeIndexingBin(); - } + if (alignment.getAlignmentStart() != SAMRecord.NO_ALIGNMENT_START) { + warnIfReferenceIsTooLargeForBinField(alignment); + indexBin = alignment.computeIndexingBinIfAbsent(alignment); } // Blurt out the elements @@ -126,8 +148,8 @@ public void encode(final SAMRecord alignment) { this.binaryCodec.writeInt(alignment.getReferenceIndex()); // 0-based!! this.binaryCodec.writeInt(alignment.getAlignmentStart() - 1); - this.binaryCodec.writeUByte((short)(alignment.getReadNameLength() + 1)); - this.binaryCodec.writeUByte((short)alignment.getMappingQuality()); + this.binaryCodec.writeUByte((short) (alignment.getReadNameLength() + 1)); + this.binaryCodec.writeUByte((short) alignment.getMappingQuality()); this.binaryCodec.writeUShort(indexBin); this.binaryCodec.writeUShort(cigarLength); this.binaryCodec.writeUShort(alignment.getFlags()); @@ -142,22 +164,22 @@ public void encode(final SAMRecord alignment) { this.binaryCodec.writeBytes(variableLengthBinaryBlock); } else { if (alignment.getReadLength() != alignment.getBaseQualities().length && - alignment.getBaseQualities().length != 0) { + alignment.getBaseQualities().length != 0) { throw new RuntimeException("Mismatch between read length and quals length writing read " + - alignment.getReadName() + "; read length: " + alignment.getReadLength() + - "; quals length: " + alignment.getBaseQualities().length); + alignment.getReadName() + "; read length: " + alignment.getReadLength() + + "; quals length: " + alignment.getBaseQualities().length); } this.binaryCodec.writeString(alignment.getReadName(), false, true); final int[] binaryCigar = BinaryCigarCodec.encode(alignment.getCigar()); for (final int cigarElement : binaryCigar) { // Assumption that this will fit into an integer, despite the fact - // that it is specced as a uint. + // that it is spec'ed as a uint. this.binaryCodec.writeInt(cigarElement); } try { this.binaryCodec.writeBytes(SAMUtils.bytesToCompressedBases(alignment.getReadBases())); - } catch ( final IllegalArgumentException ex ) { - final String msg = ex.getMessage() + " in read: " + alignment.getReadName(); + } catch (final IllegalArgumentException ex) { + final String msg = ex.getMessage() + " in read: " + alignment.getReadName(); throw new IllegalStateException(msg, ex); } byte[] qualities = alignment.getBaseQualities(); @@ -174,26 +196,63 @@ public void encode(final SAMRecord alignment) { } } + /** + * Create a "Sentinel" cigar that will be placed in BAM file when the actual cigar has more than 0xffff operator, + * which are not supported by the bam format. The actual cigar will be encoded and placed in the CG attribute. + * @param cigar actual cigar to create sentinel cigar for + * @return sentinel cigar xSyN with readLength (x) and referenceLength (y) matching the input cigar. + */ + public static Cigar makeSentinelCigar(final Cigar cigar) { + // in BAM there are only 28 bits for a cigar operator, so this a protection against overflow. + if (cigar.getReadLength() > BAMRecord.MAX_CIGAR_ELEMENT_LENGTH) { + throw new IllegalArgumentException( + String.format( + "Cannot encode (to BAM) a record with more than %d cigar operations and a read-length greater than %d.", + BAMRecord.MAX_CIGAR_OPERATORS, BAMRecord.MAX_CIGAR_ELEMENT_LENGTH)); + } + + if (cigar.getReferenceLength() > BAMRecord.MAX_CIGAR_ELEMENT_LENGTH) { + throw new IllegalArgumentException( + String.format( + "Cannot encode (to BAM) a record that has than %d cigar operations and spans more than %d bases on the reference.", + BAMRecord.MAX_CIGAR_OPERATORS, BAMRecord.MAX_CIGAR_ELEMENT_LENGTH)); + } + + return new Cigar(Arrays.asList( + new CigarElement(cigar.getReadLength(), CigarOperator.S), + new CigarElement(cigar.getReferenceLength(), CigarOperator.N))); + } + + private void warnIfReferenceIsTooLargeForBinField(final SAMRecord rec) { + final SAMSequenceRecord sequence = rec.getHeader() != null ? rec.getHeader().getSequence(rec.getReferenceName()) : null; + if (!isReferenceSizeWarningShowed + && sequence != null + && SAMUtils.isReferenceSequenceCompatibleWithBAI(sequence) + && rec.getValidationStringency() != ValidationStringency.SILENT) { + LOG.warn("Reference length is too large for BAM bin field. Values in the bin field could be incorrect."); + isReferenceSizeWarningShowed = true; + } + } + /** * Read the next record from the input stream and convert into a java object. * * @return null if no more records. Should throw exception if EOF is encountered in the middle of - * a record. + * a record. */ @Override public SAMRecord decode() { - int recordLength = 0; + final int recordLength; try { recordLength = this.binaryCodec.readInt(); - } - catch (RuntimeEOFException e) { + } catch (RuntimeEOFException e) { return null; } if (recordLength < BAMFileConstants.FIXED_BLOCK_SIZE) { throw new SAMFormatException("Invalid record length: " + recordLength); } - + final int referenceID = this.binaryCodec.readInt(); final int coordinate = this.binaryCodec.readInt() + 1; final short readNameLength = this.binaryCodec.readUByte(); diff --git a/src/main/java/htsjdk/samtools/BamFileIoUtils.java b/src/main/java/htsjdk/samtools/BamFileIoUtils.java index b5c587acc0..fddcf41240 100644 --- a/src/main/java/htsjdk/samtools/BamFileIoUtils.java +++ b/src/main/java/htsjdk/samtools/BamFileIoUtils.java @@ -15,6 +15,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Path; import java.util.List; public class BamFileIoUtils { @@ -86,7 +87,7 @@ public static void blockCopyBamFile(final File inputFile, final OutputStream out // If we found the end of the header then write the remainder of this block out as a // new gzip block and then break out of the while loop if (remainingInBlock >= 0) { - final BlockCompressedOutputStream blockOut = new BlockCompressedOutputStream(outputStream, null); + final BlockCompressedOutputStream blockOut = new BlockCompressedOutputStream(outputStream, (Path)null); IOUtil.transferByStream(blockIn, blockOut, remainingInBlock); blockOut.flush(); // Don't close blockOut because closing underlying stream would break everything diff --git a/src/main/java/htsjdk/samtools/BinaryBAMIndexWriter.java b/src/main/java/htsjdk/samtools/BinaryBAMIndexWriter.java index 5a498c3526..ec9c7e5371 100644 --- a/src/main/java/htsjdk/samtools/BinaryBAMIndexWriter.java +++ b/src/main/java/htsjdk/samtools/BinaryBAMIndexWriter.java @@ -25,6 +25,7 @@ package htsjdk.samtools; import htsjdk.samtools.util.BinaryCodec; +import htsjdk.samtools.util.IOUtil; import java.io.File; import java.io.IOException; @@ -47,7 +48,7 @@ class BinaryBAMIndexWriter implements BAMIndexWriter { * @param output BAM Index output file */ public BinaryBAMIndexWriter(final int nRef, final File output) { - this(nRef, null == output ? null : output.toPath()); + this(nRef, IOUtil.toPath(output)); } /** diff --git a/src/main/java/htsjdk/samtools/CRAMFileReader.java b/src/main/java/htsjdk/samtools/CRAMFileReader.java index a7a40889c4..889ac4c290 100644 --- a/src/main/java/htsjdk/samtools/CRAMFileReader.java +++ b/src/main/java/htsjdk/samtools/CRAMFileReader.java @@ -466,6 +466,32 @@ void enableFileSource(final SamReader reader, final boolean enabled) { iterator.setFileSource(enabled ? reader : null); } + /** + * Prepare to iterate through SAMRecords that match the intersection of the given intervals and chunk boundaries. + * @param intervals the intervals to restrict reads to + * @param contained if true, return records that are strictly + * contained in the intervals, otherwise return records that overlap + * @param filePointers file pointer pairs corresponding to chunk boundaries for the + * intervals + */ + public CloseableIterator createIndexIterator(final QueryInterval[] intervals, + final boolean contained, + final long[] filePointers) { + return new CRAMIntervalIterator(intervals, contained, filePointers); + } + + // convert queries -> merged BAMFileSpan -> coordinate array + private static long[] coordinatesFromQueryIntervals(BAMIndex index, QueryInterval[] queries) { + ArrayList spanList = new ArrayList<>(1); + Arrays.asList(queries).forEach(qi -> spanList.add(index.getSpanOverlapping(qi.referenceIndex, qi.start, qi.end))); + BAMFileSpan spanArray[] = new BAMFileSpan[spanList.size()]; + for (int i = 0; i < spanList.size(); i++) { + spanArray[i] = spanList.get(i); + } + + return BAMFileSpan.merge(spanArray).toCoordinateArray(); + } + private class CRAMIntervalIterator extends BAMQueryMultipleIntervalsIteratorFilter implements CloseableIterator { @@ -475,9 +501,12 @@ private class CRAMIntervalIterator extends BAMQueryMultipleIntervalsIteratorFilt SAMRecord nextRec = null; public CRAMIntervalIterator(final QueryInterval[] queries, final boolean contained) { + this(queries, contained, coordinatesFromQueryIntervals(getIndex(), queries)); + } + + public CRAMIntervalIterator(final QueryInterval[] queries, final boolean contained, final long[] coordinates) { super(queries, contained); - long[] coordinates = coordinatesFromQueryIntervals(getIndex(), queries); if (coordinates != null && coordinates.length != 0) { try { unfilteredIterator = new CRAMIterator( @@ -493,18 +522,6 @@ public CRAMIntervalIterator(final QueryInterval[] queries, final boolean contain } } - // convert queries -> merged BAMFileSpan -> coordinate array - private long[] coordinatesFromQueryIntervals(BAMIndex index, QueryInterval[] queries) { - ArrayList spanList = new ArrayList<>(1); - Arrays.asList(queries).forEach(qi -> spanList.add(mIndex.getSpanOverlapping(qi.referenceIndex, qi.start, qi.end))); - BAMFileSpan spanArray[] = new BAMFileSpan[spanList.size()]; - for (int i = 0; i < spanList.size(); i++) { - spanArray[i] = spanList.get(i); - } - - return BAMFileSpan.merge(spanArray).toCoordinateArray(); - } - @Override public void close() { if (unfilteredIterator != null) { diff --git a/src/main/java/htsjdk/samtools/CRAMFileWriter.java b/src/main/java/htsjdk/samtools/CRAMFileWriter.java index 2da917f60e..2f96293264 100644 --- a/src/main/java/htsjdk/samtools/CRAMFileWriter.java +++ b/src/main/java/htsjdk/samtools/CRAMFileWriter.java @@ -116,8 +116,12 @@ protected void writeAlignment(final SAMRecord alignment) { @Override protected void writeHeader(final String textHeader) { - cramContainerStream.writeHeader( - new SAMTextHeaderCodec().decode(BufferedLineReader.fromString(textHeader),fileName != null ? fileName : null)); + writeHeader(new SAMTextHeaderCodec().decode(BufferedLineReader.fromString(textHeader),fileName != null ? fileName : null)); + } + + @Override + protected void writeHeader(final SAMFileHeader header) { + cramContainerStream.writeHeader(header); } @Override diff --git a/src/main/java/htsjdk/samtools/CRAMIterator.java b/src/main/java/htsjdk/samtools/CRAMIterator.java index abe0f5d07b..2c99bcf642 100644 --- a/src/main/java/htsjdk/samtools/CRAMIterator.java +++ b/src/main/java/htsjdk/samtools/CRAMIterator.java @@ -34,9 +34,7 @@ import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; +import java.util.*; import htsjdk.samtools.cram.CRAMException; @@ -134,7 +132,6 @@ void nextContainer() throws IOException, IllegalArgumentException, nextRecord = null; return; } - container = containerIterator.next(); if (container.isEOF()) { records.clear(); @@ -255,9 +252,7 @@ public boolean hasNext() { if (!iterator.hasNext()) { try { nextContainer(); - } catch (IOException e) { - throw new SAMException(e); - } catch (IllegalAccessException e) { + } catch (IOException | IllegalAccessException e) { throw new SAMException(e); } } @@ -267,12 +262,19 @@ public boolean hasNext() { @Override public SAMRecord next() { - SAMRecord samRecord = iterator.next(); - if (validationStringency != ValidationStringency.SILENT) { - SAMUtils.processValidationErrors(samRecord.isValid(), samRecordIndex++, validationStringency); - } + if (hasNext()) { + + SAMRecord samRecord = iterator.next(); + + if (validationStringency != ValidationStringency.SILENT) { + SAMUtils.processValidationErrors(samRecord.isValid(), samRecordIndex++, validationStringency); + } - return samRecord; + return samRecord; + + } else { + throw new NoSuchElementException(); + } } @Override @@ -287,7 +289,8 @@ public void close() { try { if (countingInputStream != null) countingInputStream.close(); - } catch (final IOException e) { } + } catch (final IOException e) { + } } @Override @@ -306,4 +309,5 @@ public void setFileSource(final SamReader mReader) { public SAMFileHeader getSAMFileHeader() { return cramHeader.getSamFileHeader(); } + } diff --git a/src/main/java/htsjdk/samtools/CachingBAMFileIndex.java b/src/main/java/htsjdk/samtools/CachingBAMFileIndex.java index 5597832c21..4a1a264d92 100644 --- a/src/main/java/htsjdk/samtools/CachingBAMFileIndex.java +++ b/src/main/java/htsjdk/samtools/CachingBAMFileIndex.java @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.BitSet; import java.util.List; -import java.util.WeakHashMap; /** * Class for reading BAM file indices, caching each contig as it's loaded and @@ -37,8 +36,13 @@ */ class CachingBAMFileIndex extends AbstractBAMFileIndex implements BrowseableBAMIndex { - private Integer mLastReferenceRetrieved = null; - private final WeakHashMap mQueriesByReference = new WeakHashMap(); + // Since null is a valid return value for this index, it's possible to have lastReferenceIndex != null and + // lastReference == null, this is effectively caching the return value null + private Integer lastReferenceIndex = null; + private BAMIndexContent lastReference = null; + + private long cacheHits = 0; + private long cacheMisses = 0; public CachingBAMFileIndex(final File file, final SAMSequenceDictionary dictionary) { super(file, dictionary); @@ -110,7 +114,7 @@ public BAMFileSpan getSpanOverlapping(final Bin bin) { final int firstLocusInBin = getFirstLocusInBin(bin); // Add the specified bin to the tree if it exists. - final List binTree = new ArrayList(); + final List binTree = new ArrayList<>(); if(indexQuery.containsBin(bin)) binTree.add(indexQuery.getBins().getBin(bin.getBinNumber())); @@ -139,35 +143,31 @@ public BAMFileSpan getSpanOverlapping(final Bin bin) { * Looks up the cached BAM query results if they're still in the cache and not expired. Otherwise, * retrieves the cache results from disk. * @param referenceIndex The reference to load. CachingBAMFileIndex only stores index data for entire references. - * @return The index information for this reference. + * @return The index information for this reference or null if no index information is available for the given index. */ @Override protected BAMIndexContent getQueryResults(final int referenceIndex) { - // WeakHashMap is a bit weird in that its lookups are done via equals() equality, but expirations must be - // handled via == equality. This implementation jumps through a few hoops to make sure that == equality still - // holds even in the context of boxing/unboxing. // If this query is for the same reference index as the last query, return it. - if(mLastReferenceRetrieved!=null && mLastReferenceRetrieved == referenceIndex) - return mQueriesByReference.get(referenceIndex); - - // If not, check to see whether it's available in the cache. - BAMIndexContent queryResults = mQueriesByReference.get(referenceIndex); - if(queryResults != null) { - mLastReferenceRetrieved = referenceIndex; - mQueriesByReference.put(referenceIndex,queryResults); - return queryResults; + // This compares a boxed Integer to an int with == which is ok because the Integer will be unboxed to the primitive value + if(lastReferenceIndex!=null && lastReferenceIndex == referenceIndex){ + cacheHits++; + return lastReference; } - // If not in the cache, attempt to load it from disk. - queryResults = query(referenceIndex,1,-1); - if(queryResults != null) { - mLastReferenceRetrieved = referenceIndex; - mQueriesByReference.put(referenceIndex,queryResults); - return queryResults; - } + // If not attempt to load it from disk. + final BAMIndexContent queryResults = query(referenceIndex,1,-1); + cacheMisses++; + lastReferenceIndex = referenceIndex; + lastReference = queryResults; + return lastReference; + } + + public long getCacheHits() { + return cacheHits; + } - // Not even available on disk. - return null; + public long getCacheMisses() { + return cacheMisses; } } diff --git a/src/main/java/htsjdk/samtools/Defaults.java b/src/main/java/htsjdk/samtools/Defaults.java index 317a0e78cd..749dcdf9c7 100644 --- a/src/main/java/htsjdk/samtools/Defaults.java +++ b/src/main/java/htsjdk/samtools/Defaults.java @@ -37,24 +37,24 @@ public class Defaults { */ public static final boolean USE_ASYNC_IO_WRITE_FOR_TRIBBLE; - /** Compresion level to be used for writing BAM and other block-compressed outputs. Default = 5. */ + /** Compression level to be used for writing BAM and other block-compressed outputs. Default = 5. */ public static final int COMPRESSION_LEVEL; /** Buffer size, in bytes, used whenever reading/writing files or streams. Default = 128k. */ public static final int BUFFER_SIZE; - /** The output format of the flag field when writing SAM text. Ignored for reading SAM text. */ + /** The output format of the flag field when writing SAM text. Ignored for reading SAM text. Default = DECIMAL */ public static final SamFlagField SAM_FLAG_FIELD_FORMAT; /** * Even if BUFFER_SIZE is 0, this is guaranteed to be non-zero. If BUFFER_SIZE is non-zero, - * this == BUFFER_SIZE + * this == BUFFER_SIZE (Default = 128k). */ public static final int NON_ZERO_BUFFER_SIZE; /** * The reference FASTA file. If this is not set, the file is null. This file may be required for reading - * writing SAM files (ex. CRAM). + * writing SAM files (ex. CRAM). Default = null. */ public static final File REFERENCE_FASTA; @@ -62,36 +62,38 @@ public class Defaults { * Expected format: ,[,] * E.g. https://www.googleapis.com/genomics/v1beta/reads/,com.google.genomics.ReaderFactory * OR https://www.googleapis.com/genomics/v1beta/reads/,com.google.genomics.ReaderFactory,/tmp/genomics.jar + * Default = "". */ public static final String CUSTOM_READER_FACTORY; /** * Boolean describing whether downloading a reference file is allowed (for CRAM files), * in case the reference file is not specified by the user - * Enabling this is not necessarily a good idea, since this process often fails + * Enabling this is not necessarily a good idea, since this process often fails. Default = false. */ public static final boolean USE_CRAM_REF_DOWNLOAD; /** * A mask (pattern) to use when building EBI reference service URL for a * given MD5 checksum. Must contain one and only one string placeholder. + * Default = "https://www.ebi.ac.uk/ena/cram/md5/%s". */ public static final String EBI_REFERENCE_SERVICE_URL_MASK; /** * Boolean describing whether downloading of SRA native libraries is allowed, - * in case such native libraries are not found locally + * in case such native libraries are not found locally. Default = false. */ public static final boolean SRA_LIBRARIES_DOWNLOAD; /** - * the name of the system property that disables snappy + * The name of the system property that disables snappy. Default = "snappy.disable". */ public static final String DISABLE_SNAPPY_PROPERTY_NAME = "snappy.disable"; /** - * Disable use of the Snappy compressor + * Disable use of the Snappy compressor. Default = false. */ public static final boolean DISABLE_SNAPPY_COMPRESSOR; diff --git a/src/main/java/htsjdk/samtools/SAMBinaryTagAndValue.java b/src/main/java/htsjdk/samtools/SAMBinaryTagAndValue.java index 0778190b25..331843822a 100644 --- a/src/main/java/htsjdk/samtools/SAMBinaryTagAndValue.java +++ b/src/main/java/htsjdk/samtools/SAMBinaryTagAndValue.java @@ -202,7 +202,7 @@ else if (value instanceof float[]) { public SAMBinaryTagAndValue getNext() { return this.next; } - /** Inserts at item into the ordered list of attributes and returns the head of the list/sub-list */ + /** Inserts an item into the ordered list of attributes and returns the head of the list/sub-list */ public SAMBinaryTagAndValue insert(final SAMBinaryTagAndValue attr) { if (attr == null) return this; if (attr.next != null) throw new IllegalStateException("Can only insert single tag/value combinations."); diff --git a/src/main/java/htsjdk/samtools/SAMFileHeader.java b/src/main/java/htsjdk/samtools/SAMFileHeader.java index dd9bf5686d..935746043d 100644 --- a/src/main/java/htsjdk/samtools/SAMFileHeader.java +++ b/src/main/java/htsjdk/samtools/SAMFileHeader.java @@ -29,16 +29,8 @@ import htsjdk.samtools.util.Log; import java.io.StringWriter; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.function.Supplier; /** * Header information from a SAM or BAM file. @@ -70,40 +62,32 @@ Set getStandardTags() { * Ways in which a SAM or BAM may be sorted. */ public enum SortOrder { - unsorted(null), - queryname(SAMRecordQueryNameComparator.class), - coordinate(SAMRecordCoordinateComparator.class), - duplicate(SAMRecordDuplicateComparator.class), // NB: this is not in the SAM spec! - unknown(null); + unsorted(() -> null), + queryname(SAMRecordQueryNameComparator::new), + coordinate(SAMRecordCoordinateComparator::new), + duplicate(SAMRecordDuplicateComparator::new), // NB: this is not in the SAM spec! + unknown(() -> null); - private final Class comparator; + private final Supplier comparatorSupplier; - SortOrder(final Class comparatorClass) { - this.comparator = comparatorClass; + SortOrder(final Supplier comparatorClass) { + this.comparatorSupplier = comparatorClass; } /** * @return Comparator class to sort in the specified order, or null if unsorted. + * @deprecated since 7/2018, use {@link #getComparatorInstance()} with {@link SAMSortOrderChecker#getClass()} instead */ + @Deprecated public Class getComparator() { - return comparator; + return comparatorSupplier.get().getClass(); } /** * @return Comparator to sort in the specified order, or null if unsorted. */ public SAMRecordComparator getComparatorInstance() { - if (comparator != null) { - try { - final Constructor ctor = comparator.getConstructor(); - return ctor.newInstance(); - } - catch (Exception e) { - throw new IllegalStateException("Could not instantiate a comparator for sort order: " + - this.name(), e); - } - } - return null; + return comparatorSupplier.get(); } } @@ -262,7 +246,7 @@ public SortOrder getSortOrder() { try { return SortOrder.valueOf(so); } catch (IllegalArgumentException e) { - log.warn("Found non conforming header SO tag: " + so + ". Treating as 'unknown'."); + log.warn("Found non-conforming header SO tag: " + so + ". Treating as 'unknown'."); sortOrder = SortOrder.unknown; } } @@ -324,12 +308,18 @@ public void setAttribute(final String key, final Object value) { */ @Override public void setAttribute(final String key, final String value) { + String tempVal = value; if (key.equals(SORT_ORDER_TAG)) { this.sortOrder = null; + try { + tempVal = SortOrder.valueOf(value).toString(); + } catch (IllegalArgumentException e) { + tempVal = SortOrder.unknown.toString(); + } } else if (key.equals(GROUP_ORDER_TAG)) { this.groupOrder = null; } - super.setAttribute(key, value); + super.setAttribute(key, tempVal); } /** diff --git a/src/main/java/htsjdk/samtools/SAMFileWriterFactory.java b/src/main/java/htsjdk/samtools/SAMFileWriterFactory.java index a137efd530..d3312bb3d8 100644 --- a/src/main/java/htsjdk/samtools/SAMFileWriterFactory.java +++ b/src/main/java/htsjdk/samtools/SAMFileWriterFactory.java @@ -452,7 +452,7 @@ public SAMFileWriter makeSAMOrBAMWriter(final SAMFileHeader header, final boolea * */ public SAMFileWriter makeWriter(final SAMFileHeader header, final boolean presorted, final File outputFile, final File referenceFasta) { - return makeWriter(header, presorted, null == outputFile ? null : outputFile.toPath(), referenceFasta); + return makeWriter(header, presorted, IOUtil.toPath( outputFile ), IOUtil.toPath(referenceFasta)); } /** @@ -464,9 +464,25 @@ public SAMFileWriter makeWriter(final SAMFileHeader header, final boolean presor * @param outputPath where to write the output. Must end with .sam, .bam or .cram. * @param referenceFasta reference sequence file * @return SAMFileWriter appropriate for the file type specified in outputPath - * + * @deprecated since 6/18, use {@link #makeWriter(SAMFileHeader, boolean, Path, Path)} instead */ + @Deprecated public SAMFileWriter makeWriter(final SAMFileHeader header, final boolean presorted, final Path outputPath, final File referenceFasta) { + return makeWriter(header, presorted, outputPath, IOUtil.toPath( referenceFasta )); + } + + /** + * + * Create a SAM, BAM or CRAM writer based on examination of the outputPath extension. + * + * @param header header. Sort order is determined by the sortOrder property of this arg. + * @param presorted if true, SAMRecords must be added to the SAMFileWriter in order that agrees with header.sortOrder. + * @param outputPath where to write the output. Must end with .sam, .bam or .cram. + * @param referenceFasta reference sequence file + * @return SAMFileWriter appropriate for the file type specified in outputPath + * + */ + public SAMFileWriter makeWriter(final SAMFileHeader header, final boolean presorted, final Path outputPath, final Path referenceFasta) { if (null != outputPath && outputPath.toString().endsWith(SamReader.Type.CRAM_TYPE.fileExtension())) { return makeCRAMWriter(header, presorted, outputPath, referenceFasta); } @@ -487,6 +503,21 @@ public SAMFileWriter makeWriter(final SAMFileHeader header, final boolean presor * @return CRAMFileWriter */ public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final OutputStream stream, final File referenceFasta) { + return makeCRAMWriter(header, stream, IOUtil.toPath( referenceFasta )); + } + + /** + * Create a CRAMFileWriter on an output stream. Requires the input to be presorted to match the sort order defined + * by the input header. + * + * Note: does not honor factory settings for CREATE_MD5, CREATE_INDEX, USE_ASYNC_IO. + * + * @param header entire header. Sort order is determined by the sortOrder property of this arg. + * @param stream where to write the output. + * @param referenceFasta reference sequence file + * @return CRAMFileWriter + */ + public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final OutputStream stream, final Path referenceFasta) { // create the CRAMFileWriter directly without propagating factory settings final CRAMFileWriter writer = new CRAMFileWriter(stream, new ReferenceSource(referenceFasta), header, null); setCRAMWriterDefaults(writer); @@ -506,7 +537,7 @@ public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final OutputStr * */ public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final File outputFile, final File referenceFasta) { - return createCRAMWriterWithSettings(header, true, outputFile.toPath(), referenceFasta); + return createCRAMWriterWithSettings(header, true, outputFile.toPath(), IOUtil.toPath( referenceFasta )); } /** @@ -520,9 +551,12 @@ public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final File outp * @param referenceFasta reference sequence file * @return CRAMFileWriter * + * @deprecated since 6/18, prefer {@link #makeWriter(SAMFileHeader, boolean, Path, Path)} for creating bam/cram writers + * however {@link #makeCRAMWriter(SAMFileHeader, boolean, Path, Path)} is the direct replacement for this method */ + @Deprecated public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final Path outputPath, final File referenceFasta) { - return createCRAMWriterWithSettings(header, true, outputPath, referenceFasta); + return makeCRAMWriter(header, true, outputPath, IOUtil.toPath( referenceFasta )); } /** @@ -538,7 +572,7 @@ public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final Path outp * */ public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final boolean presorted, final File outputFile, final File referenceFasta) { - return makeCRAMWriter(header, presorted, outputFile.toPath(), referenceFasta); + return makeCRAMWriter(header, presorted, outputFile.toPath(), IOUtil.toPath(referenceFasta)); } @@ -553,8 +587,28 @@ public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final boolean p * @param referenceFasta reference sequence file * @return CRAMFileWriter * + * @deprecated since 6/18, prefer {@link #makeWriter(SAMFileHeader, boolean, Path, Path)} for creating bam/cram writers + * however {@link #makeCRAMWriter(SAMFileHeader, boolean, Path, Path)} is the direct replacement for this method + * */ + @Deprecated public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final boolean presorted, final Path output, final File referenceFasta) { + return makeCRAMWriter(header, presorted, output, IOUtil.toPath( referenceFasta )); + } + + /** + * Create a CRAMFileWriter on an output file. + * + * Note: does not honor factory setting for USE_ASYNC_IO. + * + * @param header entire header. Sort order is determined by the sortOrder property of this arg. + * @param presorted if true, SAMRecords must be added to the SAMFileWriter in order that agrees with header.sortOrder. + * @param output where to write the output. Must end with .sam, .bam or .cram. + * @param referenceFasta reference sequence file + * @return CRAMFileWriter + * + */ + public CRAMFileWriter makeCRAMWriter(final SAMFileHeader header, final boolean presorted, final Path output, final Path referenceFasta) { return createCRAMWriterWithSettings(header, presorted, output, referenceFasta); } @@ -573,7 +627,7 @@ private CRAMFileWriter createCRAMWriterWithSettings( final SAMFileHeader header, final boolean presorted, final Path outputFile, - final File referenceFasta) { + final Path referenceFasta) { OutputStream cramOS = null; OutputStream indexOS = null ; diff --git a/src/main/java/htsjdk/samtools/SAMFileWriterImpl.java b/src/main/java/htsjdk/samtools/SAMFileWriterImpl.java index 31a8604dc8..56518cd4c9 100644 --- a/src/main/java/htsjdk/samtools/SAMFileWriterImpl.java +++ b/src/main/java/htsjdk/samtools/SAMFileWriterImpl.java @@ -28,6 +28,7 @@ import java.io.File; import java.io.StringWriter; +import java.util.function.Supplier; /** * Base class for implementing SAM writer with any underlying format. @@ -105,14 +106,14 @@ protected SAMFileHeader.SortOrder getSortOrder() { * before spilling to disk. Must be called before setHeader(). * @param maxRecordsInRam */ - void setMaxRecordsInRam(final int maxRecordsInRam) { + protected void setMaxRecordsInRam(final int maxRecordsInRam) { if (this.header != null) { throw new IllegalStateException("setMaxRecordsInRam must be called before setHeader()"); } this.maxRecordsInRam = maxRecordsInRam; } - int getMaxRecordsInRam() { + protected int getMaxRecordsInRam() { return maxRecordsInRam; } @@ -121,13 +122,13 @@ int getMaxRecordsInRam() { * for spilling to disk. Must be called before setHeader(). * @param tmpDir path to the temporary directory */ - void setTempDirectory(final File tmpDir) { + protected void setTempDirectory(final File tmpDir) { if (tmpDir!=null) { this.tmpDir = tmpDir; } } - File getTempDirectory() { + protected File getTempDirectory() { return tmpDir; } @@ -144,11 +145,8 @@ public void setHeader(final SAMFileHeader header) sortOrder = SAMFileHeader.SortOrder.unsorted; } header.setSortOrder(sortOrder); - final StringWriter headerTextBuffer = new StringWriter(); - new SAMTextHeaderCodec().encode(headerTextBuffer, header); - final String headerText = headerTextBuffer.toString(); - writeHeader(headerText); + writeHeader(header); if (presorted) { if (sortOrder.equals(SAMFileHeader.SortOrder.unsorted)) { @@ -158,7 +156,7 @@ public void setHeader(final SAMFileHeader header) } } else if (!sortOrder.equals(SAMFileHeader.SortOrder.unsorted)) { alignmentSorter = SortingCollection.newInstance(SAMRecord.class, - new BAMRecordCodec(header), makeComparator(), maxRecordsInRam, tmpDir); + new BAMRecordCodec(header), sortOrder.getComparatorInstance(), maxRecordsInRam, tmpDir); } } @@ -167,20 +165,6 @@ public SAMFileHeader getFileHeader() { return header; } - private SAMRecordComparator makeComparator() { - switch (sortOrder) { - case coordinate: - return new SAMRecordCoordinateComparator(); - case queryname: - return new SAMRecordQueryNameComparator(); - case duplicate: - return new SAMRecordDuplicateComparator(); - case unsorted: - return null; - } - throw new IllegalStateException("sortOrder should not be null"); - } - /** * Add an alignment record to be emitted by the writer. * @@ -243,9 +227,27 @@ public final void close() /** * Write the header to disk. Header object is available via getHeader(). * @param textHeader for convenience if the implementation needs it. + * @deprecated since 06/2018. {@link #writeHeader(SAMFileHeader)} is preferred for avoid String construction if not need it. */ + @Deprecated abstract protected void writeHeader(String textHeader); + /** + * Write the header to disk. Header object is available via getHeader(). + * + *

IMPORTANT: this method will be abstract once {@link #writeHeader(String)} is removed. + * + *

Note: default implementation uses {@link SAMTextHeaderCodec#encode} and calls + * {@link #writeHeader(String)}. + * + * @param header object to write. + */ + protected void writeHeader(final SAMFileHeader header) { + final StringWriter headerTextBuffer = new StringWriter(); + new SAMTextHeaderCodec().encode(headerTextBuffer, header); + writeHeader(headerTextBuffer.toString()); + } + /** * Do any required flushing here. */ diff --git a/src/main/java/htsjdk/samtools/SAMLineParser.java b/src/main/java/htsjdk/samtools/SAMLineParser.java index f73a67e08e..c015aa0a5a 100644 --- a/src/main/java/htsjdk/samtools/SAMLineParser.java +++ b/src/main/java/htsjdk/samtools/SAMLineParser.java @@ -465,10 +465,9 @@ private void reportErrorParsingLine(final String reason) { private void reportErrorParsingLine(final Exception e) { final String errorMessage = makeErrorString(e.getMessage()); if (validationStringency == ValidationStringency.STRICT) { - throw new SAMFormatException(errorMessage); + throw new SAMFormatException(errorMessage, e); } else if (validationStringency == ValidationStringency.LENIENT) { - System.err - .println("Ignoring SAM validation error due to lenient parsing:"); + System.err.println("Ignoring SAM validation error due to lenient parsing:"); System.err.println(errorMessage); } } diff --git a/src/main/java/htsjdk/samtools/SAMRecord.java b/src/main/java/htsjdk/samtools/SAMRecord.java index fd8cd7c31e..c5bcbdffb1 100644 --- a/src/main/java/htsjdk/samtools/SAMRecord.java +++ b/src/main/java/htsjdk/samtools/SAMRecord.java @@ -26,8 +26,10 @@ import htsjdk.samtools.util.CoordMath; import htsjdk.samtools.util.Locatable; +import htsjdk.samtools.util.Log; import htsjdk.samtools.util.SequenceUtil; import htsjdk.samtools.util.StringUtil; +import htsjdk.samtools.util.BinaryCodec; import java.io.Serializable; import java.lang.reflect.Array; @@ -104,6 +106,8 @@ * @author mishali.naik@intel.com */ public class SAMRecord implements Cloneable, Locatable, Serializable { + private final static Log LOG = Log.getInstance(SAMRecord.class); + public static final long serialVersionUID = 1L; /** @@ -831,6 +835,12 @@ public int getCigarLength() { return getCigar().numCigarElements(); } + /** + * For setting the Cigar string when changed. Note that this nulls the + * indexing bin, which would need to be recomputed on write (if needed). + * To avoid clobbering the indexing bin, use {@link #initializeCigar} + * + */ public void setCigar(final Cigar cigar) { initializeCigar(cigar); // Change to cigar could change alignmentEnd, and thus indexing bin @@ -838,7 +848,8 @@ public void setCigar(final Cigar cigar) { } /** - * For setting the Cigar string when BAMRecord has decoded it. Use this rather than setCigar() + * For setting the Cigar string when BAMRecord has decoded it. + * Use this rather than {@link #setCigar} * so that indexing bin doesn't get clobbered. */ protected void initializeCigar(final Cigar cigar) { @@ -975,14 +986,14 @@ public boolean getNotPrimaryAlignmentFlag() { } /** - * the alignment is secondary (a read having slipt hits have multiple alignment records). + * @return whether the alignment is secondary (an alternative alignment of the read). */ public boolean isSecondaryAlignment() { return (mFlags & SAMFlag.SECONDARY_ALIGNMENT.flag) != 0; } /** - * the alignment is supplementary (TODO: further explanation?). + * @return whether the alignment is supplementary (a split alignment such as a chimeric alignment). */ public boolean getSupplementaryAlignmentFlag() { return (mFlags & SAMFlag.SUPPLEMENTARY_ALIGNMENT.flag) != 0; @@ -1080,14 +1091,14 @@ public void setNotPrimaryAlignmentFlag(final boolean flag) { } /** - * the alignment is secondary (a read having slipt hits have multiple alignment records). + * set whether this alignment is secondary (an alternative alignment of the read). */ public void setSecondaryAlignment(final boolean flag) { setFlag(flag, SAMFlag.SECONDARY_ALIGNMENT.flag); } /** - * the alignment is supplementary (TODO: further explanation?). + * set whether this alignment is supplementary (a split alignment such as a chimeric alignment). */ public void setSupplementaryAlignmentFlag(final boolean flag) { setFlag(flag, SAMFlag.SUPPLEMENTARY_ALIGNMENT.flag); @@ -1408,9 +1419,6 @@ public Object getAttribute(final short tag) { * String values are not validated to ensure that they conform to SAM spec. */ public void setAttribute(final String tag, final Object value) { - if (value != null && value.getClass().isArray() && Array.getLength(value) == 0) { - throw new IllegalArgumentException("Empty value passed for tag " + tag); - } setAttribute(SAMTagUtil.getSingleton().makeBinaryTag(tag), value); } @@ -1484,6 +1492,8 @@ public void clearAttributes() { /** * Replace any existing attributes with the given linked item. + * + * NOTE: this method is intended to only be called from subclasses. */ protected void setAttributes(final SAMBinaryTagAndValue attributes) { mAttributes = attributes; @@ -1501,7 +1511,7 @@ protected SAMBinaryTagAndValue getBinaryAttributes() { */ @Override public String getContig() { - if( getReadUnmappedFlag()) { + if (getReadUnmappedFlag()) { return null; } else { return getReferenceName(); @@ -1581,6 +1591,24 @@ int computeIndexingBin() { return GenomicIndexUtil.regionToBin(alignmentStart, alignmentEnd); } + + /** + * Gets indexing bin if it is present otherwise compute it. + * @param alignment to compute indexing bin for. + * @return indexing bin. + */ + public int computeIndexingBinIfAbsent(final SAMRecord alignment) { + if (alignment.getIndexingBin() != null) { + return alignment.getIndexingBin(); + } else { + return getUshort(alignment.computeIndexingBin()); + } + } + + private int getUshort(int value) { + return value & (int) BinaryCodec.MAX_USHORT; + } + /** * @return the SAMFileHeader for this record. If the header is null, the following SAMRecord methods may throw * exceptions: @@ -2083,13 +2111,25 @@ public List isValid(final boolean firstOnly) { if (firstOnly) return ret; } - if (this.getAlignmentStart() != NO_ALIGNMENT_START && this.getIndexingBin() != null && - this.computeIndexingBin() != this.getIndexingBin()) { - if (ret == null) ret = new ArrayList<>(); - ret.add(new SAMValidationError(SAMValidationError.Type.INVALID_INDEXING_BIN, - "bin field of BAM record does not equal value computed based on alignment start and end, and length of sequence to which read is aligned", - getReadName())); - if (firstOnly) return ret; + if (this.getAlignmentStart() != NO_ALIGNMENT_START) { + final SAMSequenceRecord sequence = getHeader() != null ? getHeader().getSequence(getReferenceName()) : null; + if (sequence != null && SAMUtils.isReferenceSequenceCompatibleWithBAI(sequence)) { + if (getValidationStringency() != ValidationStringency.SILENT) { + if (getReferenceName() != null) { + LOG.warn(String.format("%s reference length is too large for BAM bin field. %s record bin field value is incorrect.", + getReferenceName(), getReadName())); + } else { + LOG.warn(String.format("Reference length is too large for BAM bin field. %s record bin field value is incorrect.", + getReadName())); + } + } + } else if (isIndexingBinNotEqualsComputedBin()) { + if (ret == null) ret = new ArrayList<>(); + ret.add(new SAMValidationError(SAMValidationError.Type.INVALID_INDEXING_BIN, + "bin field of BAM record does not equal value computed based on alignment start and end, and length of sequence to which read is aligned", + getReadName())); + if (firstOnly) return ret; + } } if (getMateReferenceName().equals(SAMRecord.NO_ALIGNMENT_REFERENCE_NAME) && @@ -2101,7 +2141,7 @@ public List isValid(final boolean firstOnly) { if (firstOnly) return ret; } - if (getCigar().getReadLength() != 0 && getCigar().getReadLength() != getReadLength()) { + if (getReadLength() != 0 && getCigar().getReadLength() != 0 && getCigar().getReadLength() != getReadLength()) { if (ret == null) ret = new ArrayList<>(); ret.add(new SAMValidationError(SAMValidationError.Type.MISMATCH_CIGAR_SEQ_LENGTH, "CIGAR covers " + getCigar().getReadLength() + " bases but the sequence is " + getReadLength() + " read bases ", @@ -2124,6 +2164,10 @@ public List isValid(final boolean firstOnly) { return ret; } + private boolean isIndexingBinNotEqualsComputedBin() { + return this.getIndexingBin() != null && this.computeIndexingBin() != this.getIndexingBin(); + } + /** * Gets the source of this SAM record -- both the reader that retrieved the record and the position on disk from * whence it came. @@ -2264,7 +2308,7 @@ public String toString() { builder.append(" unmapped read."); } else { - builder.append(" aligned read."); + builder.append(String.format(" aligned to %s:%d-%d.", getContig(), getAlignmentStart(), getAlignmentEnd())); } return builder.toString(); diff --git a/src/main/java/htsjdk/samtools/SAMRecordSetBuilder.java b/src/main/java/htsjdk/samtools/SAMRecordSetBuilder.java index 4e7b2c9c25..8bdddb146b 100644 --- a/src/main/java/htsjdk/samtools/SAMRecordSetBuilder.java +++ b/src/main/java/htsjdk/samtools/SAMRecordSetBuilder.java @@ -65,12 +65,14 @@ public class SAMRecordSetBuilder implements Iterable { private int readLength = 36; + private boolean useBamFile = true; + private SAMProgramRecord programRecord = null; private SAMReadGroupRecord readGroup = null; private boolean useNmFlag = false; private boolean unmappedHasBasesAndQualities = true; - + public static final int DEFAULT_CHROMOSOME_LENGTH = 200000000; public static final ScoringStrategy DEFAULT_DUPLICATE_SCORING_STRATEGY = ScoringStrategy.TOTAL_MAPPED_REFERENCE_LENGTH; @@ -134,6 +136,16 @@ public SAMRecordSetBuilder(final boolean sortForMe, final SAMFileHeader.SortOrde } } + /** + * Determine whether the class will use a bam (default) or a sam file to hold the + * records when providing a reader to them. + * + * @param useBamFile if true will use a BAM file, otherwise it will use a SAM file to hold the records. + */ + public void setUseBamFile(final boolean useBamFile) { + this.useBamFile = useBamFile; + } + public void setUnmappedHasBasesAndQualities(final boolean value) { this.unmappedHasBasesAndQualities = value; } @@ -175,15 +187,20 @@ public void setReadGroup(final SAMReadGroupRecord readGroup) { } } - /** Returns the accumulated list of sam records. */ - public Collection getRecords() { return this.records; } + /** + * Returns the accumulated list of sam records. + */ + public Collection getRecords() { + return this.records; + } public void setHeader(final SAMFileHeader header) { this.header = header.clone(); } - - /** The record should already have the DS and MC tags computed */ + /** + * The record should already have the DS and MC tags computed + */ public void addRecord(final SAMRecord record) { if (record.getReadPairedFlag() && !record.getMateUnmappedFlag() && null == record.getAttribute(SAMTagUtil.getSingleton().MC)) { @@ -192,7 +209,9 @@ public void addRecord(final SAMRecord record) { this.records.add(record); } - /** Returns a CloseableIterator over the collection of SAMRecords. */ + /** + * Returns a CloseableIterator over the collection of SAMRecords. + */ @Override public CloseableIterator iterator() { return new CloseableIterator() { @@ -202,13 +221,19 @@ public CloseableIterator iterator() { public void close() { /** Do nothing. */} @Override - public boolean hasNext() { return this.iterator.hasNext(); } + public boolean hasNext() { + return this.iterator.hasNext(); + } @Override - public SAMRecord next() { return this.iterator.next(); } + public SAMRecord next() { + return this.iterator.next(); + } @Override - public void remove() { this.iterator.remove(); } + public void remove() { + this.iterator.remove(); + } }; } @@ -242,7 +267,7 @@ private SAMRecord createReadNoFlag(final String name, final int contig, final in } rec.setAttribute(SAMTag.RG.name(), READ_GROUP_ID); - if(useNmFlag){ + if (useNmFlag) { rec.setAttribute(SAMTag.NM.name(), SequenceUtil.calculateSamNmTagFromCigar(rec)); } @@ -255,7 +280,7 @@ private SAMRecord createReadNoFlag(final String name, final int contig, final in } if (!recordUnmapped || this.unmappedHasBasesAndQualities) { - fillInBasesAndQualities(rec, qualityString, defaultQuality); + fillInBasesAndQualities(rec, qualityString, defaultQuality); } return rec; @@ -306,7 +331,6 @@ public SAMRecord addFrag(final String name, final int contig, final int start, f return rec; } - /** * Fills in the bases and qualities for the given record. Quality data is randomly generated if the defaultQuality * is set to -1. Otherwise all qualities will be set to defaultQuality. If a quality string is provided that string @@ -322,11 +346,20 @@ private void fillInBasesAndQualities(final SAMRecord rec, final String qualitySt } } + /** If the record contains a cigar with non-zero read length, return that length, otherwise, return readLength + */ + private int getReadLengthFromCigar(final SAMRecord rec) { + return ( rec.getCigar() != null && + rec.getCigar().getReadLength() != 0 ) ? rec.getCigar().getReadLength() : readLength; + } + /** * Randomly fills in the bases for the given record. + *

+ * If there's a cigar with read-length >0, will use that length for reads. Otherwise will use length = 36 */ private void fillInBases(final SAMRecord rec) { - final int length = this.readLength; + final int length = getReadLengthFromCigar(rec); final byte[] bases = new byte[length]; for (int i = 0; i < length; ++i) { @@ -343,7 +376,6 @@ public void addUnmappedFragment(final String name) { addFrag(name, -1, -1, false, true, null, null, -1, false); } - /** * Adds a skeletal pair of records to the set using the provided * contig starts. The pair is assumed to be a well @@ -359,7 +391,7 @@ public void addPair(final String name, final int contig, final int start1, final end1.setAlignmentStart(start1); end1.setReadNegativeStrandFlag(false); end1.setCigarString(readLength + "M"); - if(useNmFlag) end1.setAttribute(ReservedTagConstants.NM, 0); + if (useNmFlag) end1.setAttribute(ReservedTagConstants.NM, 0); end1.setMappingQuality(255); end1.setReadPairedFlag(true); end1.setProperPairFlag(true); @@ -379,7 +411,7 @@ public void addPair(final String name, final int contig, final int start1, final end2.setAlignmentStart(start2); end2.setReadNegativeStrandFlag(true); end2.setCigarString(readLength + "M"); - if(useNmFlag) end2.setAttribute(ReservedTagConstants.NM,0); + if (useNmFlag) end2.setAttribute(ReservedTagConstants.NM, 0); end2.setMappingQuality(255); end2.setReadPairedFlag(true); end2.setProperPairFlag(true); @@ -519,10 +551,10 @@ private void fillInBasesAndQualities(final SAMRecord rec) { /** * Fills in bases and qualities with a set default quality. If the defaultQuality is set to -1 quality scores will * be randomly generated. - * Relies on the alignment start and end having been set to get read length. + * If there's a cigar with read-length >0, will use that length for reads. Otherwise will use length = 36 */ private void fillInBasesAndQualities(final SAMRecord rec, final int defaultQuality) { - final int length = this.readLength; + final int length = getReadLengthFromCigar(rec); final byte[] quals = new byte[length]; if (-1 != defaultQuality) { @@ -546,29 +578,30 @@ public SamReader getSamReader() { final File tempFile; try { - tempFile = File.createTempFile("temp", ".sam"); + tempFile = File.createTempFile("temp", this.useBamFile ? ".bam" : ".sam"); + tempFile.deleteOnExit(); } catch (final IOException e) { throw new RuntimeIOException("problems creating tempfile", e); } this.header.setAttribute("VN", "1.0"); - final SAMFileWriter w = new SAMFileWriterFactory().makeBAMWriter(this.header, true, tempFile); - for (final SAMRecord r : this.getRecords()) { - w.addAlignment(r); + try(final SAMFileWriter w = this.useBamFile ? + new SAMFileWriterFactory().makeBAMWriter(this.header, true, tempFile) : + new SAMFileWriterFactory().makeSAMWriter(this.header, true, tempFile)) { + for (final SAMRecord r : this.getRecords()) { + w.addAlignment(r); + } } - w.close(); - - final SamReader reader = SamReaderFactory.makeDefault().validationStringency(ValidationStringency.SILENT).open(tempFile); - tempFile.deleteOnExit(); - - return reader; + return SamReaderFactory.makeDefault().validationStringency(ValidationStringency.SILENT).open(tempFile); } public SAMFileHeader getHeader() { return header; } - public void setReadLength(final int readLength) { this.readLength = readLength; } + public void setReadLength(final int readLength) { + this.readLength = readLength; + } } diff --git a/src/main/java/htsjdk/samtools/SAMSequenceDictionary.java b/src/main/java/htsjdk/samtools/SAMSequenceDictionary.java index 86ffa6c9f7..be825ef396 100644 --- a/src/main/java/htsjdk/samtools/SAMSequenceDictionary.java +++ b/src/main/java/htsjdk/samtools/SAMSequenceDictionary.java @@ -31,9 +31,6 @@ import java.util.*; import java.util.stream.Collectors; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; import static htsjdk.samtools.SAMSequenceRecord.*; import static java.util.stream.Collectors.toList; @@ -41,14 +38,14 @@ /** * Collection of SAMSequenceRecords. */ -@XmlRootElement(name="References") + public class SAMSequenceDictionary implements Serializable { public static final long serialVersionUID = 1L; /* xml Serialization , for `m_sequence` we use the field instead of the getter because the later wraps the list into an unmodifiable List see http://tech.joshuacummings.com/2010/10/problems-with-defensive-collection.html */ - @XmlElement(name="Reference") + private List mSequences = new ArrayList<>(); private final Map mSequenceMap = new HashMap<>(); @@ -60,7 +57,6 @@ public SAMSequenceDictionary(final List list) { setSequences(list); } - @XmlTransient //we use the field instead of getter/setter public List getSequences() { return Collections.unmodifiableList(mSequences); } diff --git a/src/main/java/htsjdk/samtools/SAMSequenceRecord.java b/src/main/java/htsjdk/samtools/SAMSequenceRecord.java index a4b4df2369..4927a6c568 100644 --- a/src/main/java/htsjdk/samtools/SAMSequenceRecord.java +++ b/src/main/java/htsjdk/samtools/SAMSequenceRecord.java @@ -23,9 +23,7 @@ */ package htsjdk.samtools; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlValue; + import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; @@ -38,7 +36,7 @@ /** * Header information about a reference sequence. Corresponds to @SQ header record in SAM text header. */ -@XmlRootElement(name="Reference") + public class SAMSequenceRecord extends AbstractSAMHeaderRecord implements Cloneable { public static final long serialVersionUID = 1L; // AbstractSAMHeaderRecord implements Serializable @@ -99,8 +97,7 @@ public SAMSequenceRecord(final String name, final int sequenceLength) { } mSequenceLength = sequenceLength; } - - @XmlValue + public String getSequenceName() { return mSequenceName; } /* this private method is used by XML serialization */ @@ -113,27 +110,22 @@ private void setSequenceName(final String name) { mSequenceName = null; } } - - @XmlAttribute(name="length") + public int getSequenceLength() { return mSequenceLength; } public void setSequenceLength(final int value) { mSequenceLength = value; } - @XmlAttribute(name="assembly") public String getAssembly() { return (String) getAttribute(ASSEMBLY_TAG); } public void setAssembly(final String value) { setAttribute(ASSEMBLY_TAG, value); } - @XmlAttribute(name="species") public String getSpecies() { return (String) getAttribute(SPECIES_TAG); } public void setSpecies(final String value) { setAttribute(SPECIES_TAG, value); } - @XmlAttribute(name="md5") public String getMd5() { return (String) getAttribute(MD5_TAG); } public void setMd5(final String value) { setAttribute(MD5_TAG, value); } /** * @return Index of this record in the sequence dictionary it lives in. */ - @XmlAttribute(name="index") public int getSequenceIndex() { return mSequenceIndex; } // Private state used only by SAM implementation. diff --git a/src/main/java/htsjdk/samtools/SAMSortOrderChecker.java b/src/main/java/htsjdk/samtools/SAMSortOrderChecker.java index b6b7dd44e1..3483bd981b 100644 --- a/src/main/java/htsjdk/samtools/SAMSortOrderChecker.java +++ b/src/main/java/htsjdk/samtools/SAMSortOrderChecker.java @@ -34,21 +34,7 @@ public class SAMSortOrderChecker { public SAMSortOrderChecker(final SAMFileHeader.SortOrder sortOrder) { this.sortOrder = sortOrder; - switch (sortOrder) { - case coordinate: - comparator = new SAMRecordCoordinateComparator(); - break; - case queryname: - comparator = new SAMRecordQueryNameComparator(); - break; - case duplicate: - comparator = new SAMRecordDuplicateComparator(); - break; - case unsorted: - default: - comparator = null; - break; - } + this.comparator = sortOrder == null ? null : sortOrder.getComparatorInstance(); } /** @@ -71,19 +57,22 @@ public SAMRecord getPreviousRecord() { return prev; } + public SAMFileHeader.SortOrder getSortOrder() { + return sortOrder; + } + /** * Return the sort key used for the given sort order. Useful in error messages. + * This should only be used in error messages and program correctness should not rely on this. */ public String getSortKey(final SAMRecord rec) { switch (sortOrder) { - case coordinate: return rec.getReferenceName() + ":" + rec.getAlignmentStart(); case queryname: return rec.getReadName(); - case unsorted: default: - return null; + return rec.getSAMString().trim(); } } } diff --git a/src/main/java/htsjdk/samtools/SAMTag.java b/src/main/java/htsjdk/samtools/SAMTag.java index fa2572834d..41a6047773 100644 --- a/src/main/java/htsjdk/samtools/SAMTag.java +++ b/src/main/java/htsjdk/samtools/SAMTag.java @@ -32,6 +32,7 @@ public enum SAMTag { BC, BQ, CC, + CG, CM, CO, CP, diff --git a/src/main/java/htsjdk/samtools/SAMTagUtil.java b/src/main/java/htsjdk/samtools/SAMTagUtil.java index 0266b0eac6..fa69d8c3d1 100644 --- a/src/main/java/htsjdk/samtools/SAMTagUtil.java +++ b/src/main/java/htsjdk/samtools/SAMTagUtil.java @@ -70,6 +70,7 @@ public class SAMTagUtil { public final short FZ = makeBinaryTag(SAMTag.FZ.name()); public final short SA = makeBinaryTag(SAMTag.SA.name()); public final short MC = makeBinaryTag(SAMTag.MC.name()); + public final short CG = makeBinaryTag(SAMTag.CG.name()); private static SAMTagUtil singleton; diff --git a/src/main/java/htsjdk/samtools/SAMTextHeaderCodec.java b/src/main/java/htsjdk/samtools/SAMTextHeaderCodec.java index 908e8360b8..5e4f64cd34 100644 --- a/src/main/java/htsjdk/samtools/SAMTextHeaderCodec.java +++ b/src/main/java/htsjdk/samtools/SAMTextHeaderCodec.java @@ -23,10 +23,12 @@ */ package htsjdk.samtools; +import htsjdk.samtools.SAMFileHeader.SortOrder; import htsjdk.samtools.util.DateParser; import htsjdk.samtools.util.LineReader; import htsjdk.samtools.util.RuntimeIOException; import htsjdk.samtools.util.StringUtil; +import htsjdk.samtools.util.Log; import java.io.BufferedWriter; import java.io.IOException; @@ -69,6 +71,7 @@ public class SAMTextHeaderCodec { private static final Pattern FIELD_SEPARATOR_RE = Pattern.compile(FIELD_SEPARATOR); public static final String COMMENT_PREFIX = HEADER_LINE_START + HeaderRecordType.CO.name() + FIELD_SEPARATOR; + private static final Log log = Log.getInstance(SAMTextHeaderCodec.class); void setWriter(final BufferedWriter writer) { this.writer = writer; @@ -231,10 +234,10 @@ private void parseHDLine(final ParsedHeaderLine parsedHeaderLine) { final String soString = parsedHeaderLine.getValue(SAMFileHeader.SORT_ORDER_TAG); try { - if (soString != null) SAMFileHeader.SortOrder.valueOf(soString); + if (soString != null) SortOrder.valueOf(soString); } catch (IllegalArgumentException e) { reportErrorParsingLine(HEADER_LINE_START + parsedHeaderLine.getHeaderRecordType() + - " line has non-conforming SO tag value: "+ soString + ".", + " line has non-conforming SO tag value: " + soString + ".", SAMValidationError.Type.HEADER_TAG_NON_CONFORMING_VALUE, null); } @@ -323,11 +326,30 @@ private class ParsedHeaderLine { SAMValidationError.Type.HEADER_TAG_MULTIPLY_DEFINED, null); continue; } + validateSortOrderValue(keyAndValue); mKeyValuePairs.put(keyAndValue[0], keyAndValue[1]); } lineValid = true; } + private void validateSortOrderValue(String[] value) { + if (SAMFileHeader.SORT_ORDER_TAG.equals(value[0])) { + try { + SortOrder.valueOf(value[1]); + } catch (IllegalArgumentException e) { + if (validationStringency == ValidationStringency.STRICT) { + throw new SAMFormatException("Found non-conforming header SO tag: " + + value[1] + + ", exiting because VALIDATION_STRINGENCY=STRICT"); + } else if (validationStringency == ValidationStringency.LENIENT) { + log.warn("Found non-conforming header SO tag: " + + value[1] + ". Treating as 'unknown'."); + } + value[1] = SortOrder.unknown.toString(); + } + } + } + /** * True if the line is recognized as one of the valid HeaderRecordTypes. */ @@ -462,7 +484,7 @@ protected String getPGLine(final SAMProgramRecord programRecord) { private void writeRGLine(final SAMReadGroupRecord readGroup) { println(getRGLine(readGroup)); } - + protected String getRGLine(final SAMReadGroupRecord readGroup) { final String[] fields = new String[2 + readGroup.getAttributes().size()]; fields[0] = HEADER_LINE_START + HeaderRecordType.RG; @@ -525,4 +547,4 @@ public void setValidationStringency(final ValidationStringency validationStringe } this.validationStringency = validationStringency; } -} +} \ No newline at end of file diff --git a/src/main/java/htsjdk/samtools/SAMTextWriter.java b/src/main/java/htsjdk/samtools/SAMTextWriter.java index 70dd4a229a..8d9f9a91b2 100644 --- a/src/main/java/htsjdk/samtools/SAMTextWriter.java +++ b/src/main/java/htsjdk/samtools/SAMTextWriter.java @@ -198,6 +198,11 @@ public void writeHeader(final String textHeader) { } } + @Override + protected void writeHeader(final SAMFileHeader header) { + new SAMTextHeaderCodec().encode(out, header); + } + /** * Do any required flushing here. */ diff --git a/src/main/java/htsjdk/samtools/SAMUtils.java b/src/main/java/htsjdk/samtools/SAMUtils.java index 6d24f00e8b..408ff121f9 100644 --- a/src/main/java/htsjdk/samtools/SAMUtils.java +++ b/src/main/java/htsjdk/samtools/SAMUtils.java @@ -1236,4 +1236,12 @@ public static List getOtherCanonicalAlignments(final SAMRecord record } return alignments; } + + /** + * Checks if reference sequence is compatible with BAI indexing format. + * @param sequence reference sequence. + */ + public static boolean isReferenceSequenceCompatibleWithBAI(final SAMSequenceRecord sequence) { + return sequence.getSequenceLength() > GenomicIndexUtil.BIN_GENOMIC_SPAN; + } } diff --git a/src/main/java/htsjdk/samtools/SAMValidationError.java b/src/main/java/htsjdk/samtools/SAMValidationError.java index 3fb3a60b07..55cb71a0b9 100644 --- a/src/main/java/htsjdk/samtools/SAMValidationError.java +++ b/src/main/java/htsjdk/samtools/SAMValidationError.java @@ -226,7 +226,13 @@ public enum Type { MISMATCH_FILE_SEQ_DICT, /** Base quality is not stored for the read. */ - QUALITY_NOT_STORED(Severity.WARNING); + QUALITY_NOT_STORED(Severity.WARNING), + + /** A duplicate Sam tag was found in a record. */ + DUPLICATE_SAM_TAG, + + /** The CG Tag should only be used in BAM format to hold a large cigar */ + CG_TAG_FOUND_IN_ATTRIBUTES; public final Severity severity; diff --git a/src/main/java/htsjdk/samtools/SamFileValidator.java b/src/main/java/htsjdk/samtools/SamFileValidator.java index 013b40b6f5..31aab8d4ad 100644 --- a/src/main/java/htsjdk/samtools/SamFileValidator.java +++ b/src/main/java/htsjdk/samtools/SamFileValidator.java @@ -208,10 +208,8 @@ public boolean validateSamFileVerbose(final SamReader samReader, final Reference } public void validateBamFileTermination(final File inputFile) { - BufferedInputStream inputStream = null; try { - inputStream = IOUtil.toBufferedStream(new FileInputStream(inputFile)); - if (!BlockCompressedInputStream.isValidFile(inputStream)) { + if (!IOUtil.isBlockCompressed(inputFile.toPath())) { return; } final BlockCompressedInputStream.FileTermination terminationState = @@ -227,10 +225,6 @@ public void validateBamFileTermination(final File inputFile) { } } catch (IOException e) { throw new SAMException("IOException", e); - } finally { - if (inputStream != null) { - CloserUtil.close(inputStream); - } } } @@ -244,8 +238,7 @@ private void validateSamFile(final SamReader samReader, final PrintWriter out) { try { if (indexValidationStringency == IndexValidationStringency.LESS_EXHAUSTIVE) { BamIndexValidator.lessExhaustivelyTestIndex(samReader); - } - else { + } else { BamIndexValidator.exhaustivelyTestIndex(samReader); } } catch (Exception e) { @@ -344,7 +337,7 @@ private void validateSamRecordsAndQualityFormat(final Iterable samRec } - if ((qualityNotStoredErrorCount++ < MAX_QUALITY_NOT_STORED_ERRORS) && record.getBaseQualityString().equals("*")){ + if ((qualityNotStoredErrorCount++ < MAX_QUALITY_NOT_STORED_ERRORS) && record.getBaseQualityString().equals("*")) { addError(new SAMValidationError(Type.QUALITY_NOT_STORED, "QUAL field is set to * (unspecified quality scores), this is allowed by the SAM" + " specification but many tools expect reads to include qualities ", @@ -390,15 +383,33 @@ private void validateReadGroup(final SAMRecord record, final SAMFileHeader heade } /** - * Report error if a tag value is a Long. + * Report error if a tag value is a Long, or if there's a duplicate dag, + * or if there's a CG tag is obvered (CG tags are converted to cigars in + * the bam code, and should not appear in other formats) */ private void validateTags(final SAMRecord record, final long recordNumber) { - for (final SAMRecord.SAMTagAndValue tagAndValue : record.getAttributes()) { + final List attributes = record.getAttributes(); + + final Set tags = new HashSet<>(attributes.size()); + + for (final SAMRecord.SAMTagAndValue tagAndValue : attributes) { if (tagAndValue.value instanceof Long) { addError(new SAMValidationError(Type.TAG_VALUE_TOO_LARGE, "Numeric value too large for tag " + tagAndValue.tag, record.getReadName(), recordNumber)); } + + if (!tags.add(tagAndValue.tag)) { + addError(new SAMValidationError(Type.DUPLICATE_SAM_TAG, + "Duplicate SAM tag (" + tagAndValue.tag + ") found.", record.getReadName(), recordNumber)); + } + } + + if (tags.contains(SAMTag.CG.name())){ + addError(new SAMValidationError(Type.CG_TAG_FOUND_IN_ATTRIBUTES, + "The CG Tag should only be used in BAM format to hold a large cigar. " + + "It was found containing the value: " + + record.getAttribute(SAMTagUtil.getSingleton().CG), record.getReadName(), recordNumber)); } } @@ -457,7 +468,6 @@ private boolean validateCigar(final SAMRecord record, final long recordNumber, f return valid; } - private boolean validateSortOrder(final SAMRecord record, final long recordNumber) { final SAMRecord prev = orderChecker.getPreviousRecord(); boolean isValidSortOrder = orderChecker.isSorted(record); @@ -593,8 +603,7 @@ private void validateHeader(final SAMFileHeader fileHeader) { addError(new SAMValidationError(Type.MISSING_PLATFORM_VALUE, "A platform (PL) attribute was not found for read group ", readGroupID)); - } - else { + } else { // NB: cannot be null, so not catching a NPE try { SAMReadGroupRecord.PlatformValue.valueOf(platformValue.toUpperCase()); @@ -631,7 +640,7 @@ private void addError(final SAMValidationError error) { switch (error.getType().severity) { case WARNING: - if ( this.ignoreWarnings ) { + if (this.ignoreWarnings) { return; } this.numWarnings++; diff --git a/src/main/java/htsjdk/samtools/SamFiles.java b/src/main/java/htsjdk/samtools/SamFiles.java index 874fc1027e..f69ab0e695 100644 --- a/src/main/java/htsjdk/samtools/SamFiles.java +++ b/src/main/java/htsjdk/samtools/SamFiles.java @@ -3,6 +3,7 @@ import htsjdk.samtools.cram.CRAIIndex; import htsjdk.samtools.cram.build.CramIO; +import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.Log; import java.io.File; import java.io.IOException; @@ -24,7 +25,7 @@ public class SamFiles { * @return The index for the provided SAM, or null if one was not found. */ public static File findIndex(final File samFile) { - Path path = findIndex(samFile.toPath()); + final Path path = findIndex(IOUtil.toPath(samFile)); return path == null ? null : path.toFile(); } diff --git a/src/main/java/htsjdk/samtools/SamInputResource.java b/src/main/java/htsjdk/samtools/SamInputResource.java index a039e5aa3f..c68b6327a7 100644 --- a/src/main/java/htsjdk/samtools/SamInputResource.java +++ b/src/main/java/htsjdk/samtools/SamInputResource.java @@ -33,17 +33,14 @@ import htsjdk.samtools.util.Lazy; import htsjdk.samtools.util.RuntimeIOException; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.MalformedURLException; -import java.net.URISyntaxException; import java.net.URL; import java.nio.channels.SeekableByteChannel; import java.nio.file.FileSystemNotFoundException; +import java.nio.file.FileSystems; +import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.function.Function; import java.util.function.Supplier; @@ -90,11 +87,30 @@ public String toString() { } /** Creates a {@link SamInputResource} reading from the provided resource, with no index. */ - public static SamInputResource of(final File file) { return new SamInputResource(new FileInputResource(file)); } + public static SamInputResource of(final File file) { + return new SamInputResource(new FileInputResource(file)); + } /** Creates a {@link SamInputResource} reading from the provided resource, with no index. */ public static SamInputResource of(final Path path) { - return new SamInputResource(new PathInputResource(path)); + + // in the case of named pipes and other non-seekable paths there's a bug in the implementation of + // java's GZIPInputStream which inappropriately uses .available() and then gets confused with the result + // of 0. For reference see: + // https://bugs.java.com/view_bug.do?bug_id=7036144 + // https://github.com/samtools/htsjdk/pull/1077 + // https://github.com/samtools/htsjdk/issues/898 + + // This still doesn't support the case where someone is creating a named pipe in a non-default + // file system and then using it as input and passing a GZIPed into the other end of the pipe. + + // To work around this bug, we fall back to using a FileInputResource rather than a PathInputResource + // when we encounter a non-regular file using the default NIO filesystem (file://) + if (path.getFileSystem() == FileSystems.getDefault() && !Files.isRegularFile(path)) { + return of(path.toFile()); + } else { + return new SamInputResource(new PathInputResource(path)); + } } /** Creates a {@link SamInputResource} reading from the provided resource, with no index, @@ -255,7 +271,7 @@ public File asFile() { @Override public Path asPath() { - return fileResource.toPath(); + return IOUtil.toPath(fileResource); } @Override @@ -269,12 +285,27 @@ public URL asUrl() { @Override public SeekableStream asUnbufferedSeekableStream() { - return lazySeekableStream.get(); + //if the file doesn't exist, the try to open the stream anyway because users might be expecting the exception + //if it not a regular file than we won't be able to seek on it, so return null + if (!fileResource.exists() || fileResource.isFile()) { + return lazySeekableStream.get(); + } else { + return null; + } } @Override public InputStream asUnbufferedInputStream() { - return asUnbufferedSeekableStream(); + final SeekableStream seekableStream = asUnbufferedSeekableStream(); + if (seekableStream != null) { + return seekableStream; + } else { + try { + return new FileInputStream(fileResource); + } catch (FileNotFoundException e) { + throw new RuntimeIOException(e); + } + } } @Override diff --git a/src/main/java/htsjdk/samtools/SamReader.java b/src/main/java/htsjdk/samtools/SamReader.java index 08f93ec179..f7062886f3 100644 --- a/src/main/java/htsjdk/samtools/SamReader.java +++ b/src/main/java/htsjdk/samtools/SamReader.java @@ -43,13 +43,13 @@ public interface SamReader extends Iterable, Closeable { /** Describes a type of SAM file. */ public abstract class Type { /** A string representation of this type. */ - abstract String name(); + public abstract String name(); /** The recommended file extension for SAMs of this type, without a period. */ public abstract String fileExtension(); /** The recommended file extension for SAM indexes of this type, without a period, or null if this type is not associated with indexes. */ - abstract String indexExtension(); + public abstract String indexExtension(); static class TypeImpl extends Type { final String name, fileExtension, indexExtension; @@ -61,7 +61,7 @@ static class TypeImpl extends Type { } @Override - String name() { + public String name() { return name; } @@ -71,7 +71,7 @@ public String fileExtension() { } @Override - String indexExtension() { + public String indexExtension() { return indexExtension; } @@ -81,10 +81,10 @@ public String toString() { } } - public static Type SRA_TYPE = new TypeImpl("SRA", "sra", null); - public static Type CRAM_TYPE = new TypeImpl("CRAM", "cram", "crai"); - public static Type BAM_TYPE = new TypeImpl("BAM", "bam", "bai"); - public static Type SAM_TYPE = new TypeImpl("SAM", "sam", null); + public static final Type SRA_TYPE = new TypeImpl("SRA", "sra", null); + public static final Type CRAM_TYPE = new TypeImpl("CRAM", "cram", "crai"); + public static final Type BAM_TYPE = new TypeImpl("BAM", "bam", "bai"); + public static final Type SAM_TYPE = new TypeImpl("SAM", "sam", null); } /** @@ -552,8 +552,7 @@ static AssertingIterator of(final CloseableIterator iterator) { } private final CloseableIterator wrappedIterator; - private SAMRecord previous = null; - private SAMRecordComparator comparator = null; + private SAMSortOrderChecker checker; public AssertingIterator(final CloseableIterator iterator) { wrappedIterator = iterator; @@ -561,35 +560,21 @@ public AssertingIterator(final CloseableIterator iterator) { @Override public SAMRecordIterator assertSorted(final SAMFileHeader.SortOrder sortOrder) { - - if (sortOrder == null || sortOrder == SAMFileHeader.SortOrder.unsorted) { - comparator = null; - return this; - } - - comparator = sortOrder.getComparatorInstance(); + checker = new SAMSortOrderChecker(sortOrder); return this; } @Override public SAMRecord next() { final SAMRecord result = wrappedIterator.next(); - if (comparator != null) { - if (previous != null) { - if (comparator.fileOrderCompare(previous, result) > 0) { - throw new IllegalStateException(MessageFormat.format( - "Records {0} ({1}:{2}) should come after {3} ({4}:{5}) when sorting with {6}", - previous.getReadName(), - previous.getReferenceName(), - previous.getAlignmentStart(), - result.getReadName(), - result.getReferenceName(), - result.getAlignmentStart(), - comparator.getClass().getName()) - ); - } + if (checker != null) { + final SAMRecord previous = checker.getPreviousRecord(); + if (!checker.isSorted(result)) { + throw new IllegalStateException(String.format( + "Record %s should come after %s when sorting with %s ordering.", + previous.getSAMString().trim(), + result.getSAMString().trim(), checker.getSortOrder())); } - previous = result; } return result; } diff --git a/src/main/java/htsjdk/samtools/SamReaderFactory.java b/src/main/java/htsjdk/samtools/SamReaderFactory.java index 132e576008..372c5a3a11 100644 --- a/src/main/java/htsjdk/samtools/SamReaderFactory.java +++ b/src/main/java/htsjdk/samtools/SamReaderFactory.java @@ -406,7 +406,17 @@ public SamReader open(final SamInputResource resource) { referenceSource = ReferenceSource.getDefaultCRAMReferenceSource(); } if (sourceFile == null || !sourceFile.isFile()) { - primitiveSamReader = new CRAMFileReader(bufferedStream, indexFile, referenceSource, validationStringency); + final SeekableStream indexSeekableStream = + indexMaybe == null ? + null : + indexMaybe.asUnbufferedSeekableStream(); + final SeekableStream sourceSeekableStream = data.asUnbufferedSeekableStream(); + if (null == sourceSeekableStream || null == indexSeekableStream) { + primitiveSamReader = new CRAMFileReader(bufferedStream, indexFile, referenceSource, validationStringency); + } else { + sourceSeekableStream.seek(0); + primitiveSamReader = new CRAMFileReader(sourceSeekableStream, indexSeekableStream, referenceSource, validationStringency); + } } else { bufferedStream.close(); primitiveSamReader = new CRAMFileReader(sourceFile, indexFile, referenceSource, validationStringency); diff --git a/src/main/java/htsjdk/samtools/TextTagCodec.java b/src/main/java/htsjdk/samtools/TextTagCodec.java index 40dc8ac73f..e86bef0412 100644 --- a/src/main/java/htsjdk/samtools/TextTagCodec.java +++ b/src/main/java/htsjdk/samtools/TextTagCodec.java @@ -44,6 +44,8 @@ public class TextTagCodec { // 3 fields for non-empty strings 2 fields if the string is empty. private static final int NUM_TAG_FIELDS = 3; + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + /** * This is really a local variable of decode(), but allocated here to reduce allocations. */ @@ -52,7 +54,7 @@ public class TextTagCodec { /** * Convert in-memory representation of tag to SAM text representation. * @param tagName Two-character tag name. - * @param value Tag value as approriate Object subclass. + * @param value Tag value as appropriate Object subclass. * @return SAM text String representation, i.e. name:type:value */ public String encode(final String tagName, Object value) { @@ -71,7 +73,7 @@ public String encode(final String tagName, Object value) { // H should never happen anymore. value = StringUtil.bytesToHexString((byte[])value); } else if (tagType == 'B') { - value = getArrayType(value, false) + "," + encodeArrayValue(value); + value = getArrayType(value, false) + encodeArrayValue(value); } else if (tagType == 'i') { final long longVal = ((Number) value).longValue(); // as the spec says: [-2^31, 2^32) @@ -83,7 +85,7 @@ public String encode(final String tagName, Object value) { return sb.toString(); } - private char getArrayType(final Object array, final boolean isUnsigned) { + private static char getArrayType(final Object array, final boolean isUnsigned) { final char type; final Class componentType = array.getClass().getComponentType(); if (componentType == Float.TYPE) { @@ -97,10 +99,10 @@ private char getArrayType(final Object array, final boolean isUnsigned) { return (isUnsigned? Character.toUpperCase(type): type); } - private String encodeArrayValue(final Object value) { - final StringBuilder ret = new StringBuilder(Array.get(value, 0).toString()); + private static String encodeArrayValue(final Object value) { final int length = Array.getLength(value); - for (int i = 1; i < length; ++i) { + final StringBuilder ret = new StringBuilder(); + for (int i = 0; i < length; ++i) { ret.append(','); ret.append(Array.get(value, i).toString()); } @@ -108,7 +110,7 @@ private String encodeArrayValue(final Object value) { } - private long[] widenToUnsigned(final Object array) { + private static long[] widenToUnsigned(final Object array) { final Class componentType = array.getClass().getComponentType(); final long mask; if (componentType == Byte.TYPE) mask = 0xffL; @@ -127,7 +129,7 @@ String encodeUnsignedArray(final String tagName, final Object array) { throw new IllegalArgumentException("Non-array passed to encodeUnsignedArray: " + array.getClass()); } final long[] widened = widenToUnsigned(array); - return tagName + ":B:" + getArrayType(array, true) + "," + encodeArrayValue(widened); + return tagName + ":B:" + getArrayType(array, true) + encodeArrayValue(widened); } /** @@ -175,7 +177,7 @@ public Object setValue(final Object o) { }; } - private Object convertStringToObject(final String type, final String stringVal) { + private static Object convertStringToObject(final String type, final String stringVal) { if (type.equals("Z")) { return stringVal; } else if (type.equals("A")) { @@ -219,17 +221,18 @@ else if (SAMUtils.isValidUnsignedIntegerAttribute(lValue)) { } } - private Object covertStringArrayToObject(final String stringVal) { + private static Object covertStringArrayToObject(final String stringVal) { final String[] elementTypeAndValue = new String[2]; - if (StringUtil.splitConcatenateExcessTokens(stringVal, elementTypeAndValue, ',') != 2) { - throw new SAMFormatException("Tag of type B should have an element type followed by comma"); - } + + final int numberOfTokens = StringUtil.splitConcatenateExcessTokens(stringVal, elementTypeAndValue, ','); + if (elementTypeAndValue[0].length() != 1) { throw new SAMFormatException("Unrecognized element type for array tag value: " + elementTypeAndValue[0]); } + final char elementType = elementTypeAndValue[0].charAt(0); - final String[] stringValues = elementTypeAndValue[1].split(","); - if (stringValues.length == 0) throw new SAMFormatException("Tag of type B should have at least one element"); + + final String[] stringValues = elementTypeAndValue[1] != null ? elementTypeAndValue[1].split(",") : EMPTY_STRING_ARRAY; if (elementType == 'f') { final float[] ret = new float[stringValues.length]; for (int i = 0; i < stringValues.length; ++i) { diff --git a/src/main/java/htsjdk/samtools/cram/build/CramContainerHeaderIterator.java b/src/main/java/htsjdk/samtools/cram/build/CramContainerHeaderIterator.java new file mode 100644 index 0000000000..4c3264596a --- /dev/null +++ b/src/main/java/htsjdk/samtools/cram/build/CramContainerHeaderIterator.java @@ -0,0 +1,32 @@ +package htsjdk.samtools.cram.build; + +import htsjdk.samtools.cram.common.Version; +import htsjdk.samtools.cram.io.CountingInputStream; +import htsjdk.samtools.cram.io.InputStreamUtils; +import htsjdk.samtools.cram.structure.Container; +import htsjdk.samtools.cram.structure.ContainerIO; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Iterate over CRAM containers from an input stream, and unlike {@link CramContainerIterator} only + * the header of each container is read, rather than the whole stream. As a result, the container block + * data is *not* populated, including the compression header block and slices. + * + * This class is useful when you are not interested in the contents of containers, for example when indexing container + * start positions. + */ +public class CramContainerHeaderIterator extends CramContainerIterator { + + public CramContainerHeaderIterator(final InputStream inputStream) throws IOException { + super(inputStream); + } + + protected Container containerFromStream(final Version cramVersion, final CountingInputStream countingStream) throws IOException { + final Container container = ContainerIO.readContainerHeader(cramVersion.major, countingStream); + InputStreamUtils.skipFully(countingStream, container.containerByteSize); + return container; + } + +} diff --git a/src/main/java/htsjdk/samtools/cram/build/CramContainerIterator.java b/src/main/java/htsjdk/samtools/cram/build/CramContainerIterator.java index a38e6b8dce..159de03f90 100644 --- a/src/main/java/htsjdk/samtools/cram/build/CramContainerIterator.java +++ b/src/main/java/htsjdk/samtools/cram/build/CramContainerIterator.java @@ -1,5 +1,6 @@ package htsjdk.samtools.cram.build; +import htsjdk.samtools.cram.common.Version; import htsjdk.samtools.cram.io.CountingInputStream; import htsjdk.samtools.cram.structure.Container; import htsjdk.samtools.cram.structure.ContainerIO; @@ -14,21 +15,21 @@ */ public class CramContainerIterator implements Iterator { private CramHeader cramHeader; - private InputStream inputStream; + private CountingInputStream countingInputStream; private Container nextContainer; private boolean eof = false; private long offset = 0; public CramContainerIterator(final InputStream inputStream) throws IOException { - cramHeader = CramIO.readCramHeader(inputStream); - this.inputStream = inputStream; + this.countingInputStream = new CountingInputStream(inputStream); + cramHeader = CramIO.readCramHeader(countingInputStream); + this.offset = countingInputStream.getCount(); } void readNextContainer() { try { - final CountingInputStream cis = new CountingInputStream(inputStream); - nextContainer = ContainerIO.readContainer(cramHeader.getVersion(), cis); - final long containerSizeInBytes = cis.getCount(); + nextContainer = containerFromStream(cramHeader.getVersion(), countingInputStream); + final long containerSizeInBytes = countingInputStream.getCount() - offset; nextContainer.offset = offset; offset += containerSizeInBytes; @@ -42,6 +43,17 @@ void readNextContainer() { } } + /** + * Consume the entirety of the next container from the stream. + * @param cramVersion + * @param countingStream + * @return The next Container from the stream. + * @throws IOException + */ + protected Container containerFromStream(final Version cramVersion, final CountingInputStream countingStream) throws IOException { + return ContainerIO.readContainer(cramHeader.getVersion(), countingStream); + } + @Override public boolean hasNext() { if (eof) return false; @@ -70,7 +82,7 @@ public void close() { cramHeader = null; //noinspection EmptyCatchBlock try { - inputStream.close(); + countingInputStream.close(); } catch (final Exception e) { } } diff --git a/src/main/java/htsjdk/samtools/cram/encoding/BetaIntegerCodec.java b/src/main/java/htsjdk/samtools/cram/encoding/BetaIntegerCodec.java index 496f5a63be..d96b46ef2a 100644 --- a/src/main/java/htsjdk/samtools/cram/encoding/BetaIntegerCodec.java +++ b/src/main/java/htsjdk/samtools/cram/encoding/BetaIntegerCodec.java @@ -22,36 +22,70 @@ import java.io.IOException; - +/** + * Encodes integers by adding a constant offset value to a range of values in order to reduce + * the necessary number of bits needed to store each value. + * + * As a simple example, consider a data series with values all in the range 10,000 - 10,100. + * Choosing the offset -10,000 means every encoded value will be stored as 0 - 100, + * requiring only ceil(log2(100)) = 7 bits per value. + */ class BetaIntegerCodec extends AbstractBitCodec { - private int offset = 0; - private final int readNofBits; + private final int offset; + private final int bitsPerValue; + private final long valueLimit; // 1 << bitsPerValue (max 32) so int is too small + + /** + * Given integers to encode in the range MIN to MAX: + * + * @param offset the common value to be added to all values before storage. + * Setting this to (-MIN) will ensure all stored values will be in the range (0 .. MAX - MIN) + * @param bitsPerValue the smallest value which will allow the largest stored value (MAX - MIN) + */ + public BetaIntegerCodec(final int offset, final int bitsPerValue) { + if (bitsPerValue <= 0) { + throw new IllegalArgumentException("Number of bits per value must be positive"); + } else if (bitsPerValue > 32) { + throw new IllegalArgumentException("Number of bits per value must be 32 or lower"); + } - public BetaIntegerCodec(final int offset, final int readNofBits) { this.offset = offset; - this.readNofBits = readNofBits; + this.bitsPerValue = bitsPerValue; + this.valueLimit = 1L << bitsPerValue; } @Override public final Integer read(final BitInputStream bitInputStream) throws IOException { - return bitInputStream.readBits(readNofBits) - offset; + return bitInputStream.readBits(bitsPerValue) - offset; + } + + private int getAndCheckOffsetValue(int value) { + final int newValue = value + offset; + + if (newValue < 0) { + String negative = String.format("Value %s plus offset %s must be positive", + value, offset); + throw new IllegalArgumentException(negative); + } else if (newValue >= valueLimit) { + String tooBig = String.format("Value %s plus offset %s is greater than or equal to limit %s", + value, offset, valueLimit); + throw new IllegalArgumentException(tooBig); + } + + return newValue; } @Override public final long write(final BitOutputStream bitOutputStream, final Integer value) throws IOException { - final int nofBits = (int) numberOfBits(value); - final long newValue = value + offset; - bitOutputStream.write(newValue, nofBits); - return nofBits; + bitOutputStream.write(getAndCheckOffsetValue(value), bitsPerValue); + // every value is encoded using the same number of bits + return bitsPerValue; } @Override public final long numberOfBits(final Integer value) { - if (value > (1L << readNofBits)) - throw new IllegalArgumentException("Value written is bigger then allowed: value=" + value - + ", max nof bits=" + readNofBits); - - return readNofBits; + // every value is encoded using the same number of bits + return bitsPerValue; } @Override diff --git a/src/main/java/htsjdk/samtools/cram/io/CramInt.java b/src/main/java/htsjdk/samtools/cram/io/CramInt.java index 1b0432f9b6..58a14d15db 100644 --- a/src/main/java/htsjdk/samtools/cram/io/CramInt.java +++ b/src/main/java/htsjdk/samtools/cram/io/CramInt.java @@ -17,7 +17,7 @@ public class CramInt { * @return an integer value read * @throws IOException as per java IO contract */ - public static int int32(final InputStream inputStream) throws IOException { + public static int readInt32(final InputStream inputStream) throws IOException { return inputStream.read() | inputStream.read() << 8 | inputStream.read() << 16 | inputStream.read() << 24; } @@ -27,7 +27,7 @@ public static int int32(final InputStream inputStream) throws IOException { * @param data input stream to read from * @return an integer value read */ - public static int int32(final byte[] data) { + public static int readInt32(final byte[] data) { if (data.length != 4) throw new IllegalArgumentException("Expecting a 4-byte integer. "); return (0xFF & data[0]) | ((0xFF & data[1]) << 8) | ((0xFF & data[2]) << 16) | ((0xFF & data[3]) << 24); @@ -39,8 +39,11 @@ public static int int32(final byte[] data) { * @param buffer {@link ByteBuffer} to read from * @return an integer value read from the buffer */ - public static int int32(final ByteBuffer buffer) { - return buffer.get() | buffer.get() << 8 | buffer.get() << 16 | buffer.get() << 24; + public static int readInt32(final ByteBuffer buffer) { + return (0xFF & buffer.get()) | + (0xFF & buffer.get()) << 8 | + (0xFF & buffer.get()) << 16 | + (0xFF & buffer.get()) << 24; } /** @@ -61,7 +64,7 @@ public static int writeInt32(final int value, final OutputStream outputStream) t } /** - * Write int value to {@link OutputStream} encoded as CRAM int data type. + * Write int value to an array of bytes encoded as CRAM int data type. * * @param value value to be written out * @return the byte array holding the value encoded as CRAM int data type @@ -74,5 +77,4 @@ public static byte[] writeInt32(final int value) { data[3] = (byte) (value >> 24 & 0xFF); return data; } - } diff --git a/src/main/java/htsjdk/samtools/cram/io/CramArray.java b/src/main/java/htsjdk/samtools/cram/io/CramIntArray.java similarity index 97% rename from src/main/java/htsjdk/samtools/cram/io/CramArray.java rename to src/main/java/htsjdk/samtools/cram/io/CramIntArray.java index 819319e476..8ce5421de5 100644 --- a/src/main/java/htsjdk/samtools/cram/io/CramArray.java +++ b/src/main/java/htsjdk/samtools/cram/io/CramIntArray.java @@ -7,7 +7,7 @@ /** * Methods to read and write CRAM array of integers data type. */ -public class CramArray { +public class CramIntArray { /** * Read CRAM int array from a {@link InputStream}. * diff --git a/src/main/java/htsjdk/samtools/cram/io/InputStreamUtils.java b/src/main/java/htsjdk/samtools/cram/io/InputStreamUtils.java index 3d1c96da9e..7a62752dc9 100644 --- a/src/main/java/htsjdk/samtools/cram/io/InputStreamUtils.java +++ b/src/main/java/htsjdk/samtools/cram/io/InputStreamUtils.java @@ -77,4 +77,29 @@ public static void readFully(final InputStream inputStream, final byte[] b, fina n += count; } } + + /** + * Skip the specified number of bytes from the {@link InputStream}. + * @param in the input stream to skip bytes from + * @param length the number of bytes to skip + * @throws IOException as per java IO contract + * @throws EOFException if there is less than length bytes in the stream + */ + public static void skipFully(final InputStream in, final long length) throws IOException { + long amt = length; + while (amt > 0) { + long ret = in.skip(amt); + if (ret == 0) { + // skip may return 0 even if we're not at EOF. Luckily, we can + // use the read() method to figure out if we're at the end. + int b = in.read(); + if (b == -1) { + throw new EOFException( "Premature EOF from inputStream after " + + "skipping " + (length - amt) + " byte(s)."); + } + ret = 1; + } + amt -= ret; + } + } } diff --git a/src/main/java/htsjdk/samtools/cram/ref/ReferenceSource.java b/src/main/java/htsjdk/samtools/cram/ref/ReferenceSource.java index 61b3a418b0..1264fee09b 100644 --- a/src/main/java/htsjdk/samtools/cram/ref/ReferenceSource.java +++ b/src/main/java/htsjdk/samtools/cram/ref/ReferenceSource.java @@ -20,12 +20,11 @@ import htsjdk.samtools.Defaults; import htsjdk.samtools.SAMException; import htsjdk.samtools.SAMSequenceRecord; -import htsjdk.samtools.SAMUtils; -import htsjdk.samtools.cram.build.Utils; import htsjdk.samtools.cram.io.InputStreamUtils; import htsjdk.samtools.reference.ReferenceSequence; import htsjdk.samtools.reference.ReferenceSequenceFile; import htsjdk.samtools.reference.ReferenceSequenceFileFactory; +import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.Log; import htsjdk.samtools.util.SequenceUtil; import htsjdk.samtools.util.StringUtil; @@ -60,7 +59,7 @@ public class ReferenceSource implements CRAMReferenceSource { private final Map> cacheW = new HashMap<>(); public ReferenceSource(final File file) { - this(file == null ? null : file.toPath()); + this(IOUtil.toPath(file)); } public ReferenceSource(final Path path) { diff --git a/src/main/java/htsjdk/samtools/cram/structure/Block.java b/src/main/java/htsjdk/samtools/cram/structure/Block.java index 2e99b8a76c..b74577a2f8 100644 --- a/src/main/java/htsjdk/samtools/cram/structure/Block.java +++ b/src/main/java/htsjdk/samtools/cram/structure/Block.java @@ -91,7 +91,7 @@ public static Block readFromInputStream(final int major, InputStream inputStream InputStreamUtils.readFully(inputStream, block.compressedContent, 0, block.compressedContent.length); if (v3OrHigher) { final int actualChecksum = ((CRC32InputStream) inputStream).getCRC32(); - final int checksum = CramInt.int32(inputStream); + final int checksum = CramInt.readInt32(inputStream); if (checksum != actualChecksum) throw new RuntimeException(String.format("Block CRC32 mismatch: %04x vs %04x", checksum, actualChecksum)); } diff --git a/src/main/java/htsjdk/samtools/cram/structure/ContainerHeaderIO.java b/src/main/java/htsjdk/samtools/cram/structure/ContainerHeaderIO.java index fd6edfe178..7e6e203f13 100644 --- a/src/main/java/htsjdk/samtools/cram/structure/ContainerHeaderIO.java +++ b/src/main/java/htsjdk/samtools/cram/structure/ContainerHeaderIO.java @@ -18,7 +18,7 @@ package htsjdk.samtools.cram.structure; import htsjdk.samtools.cram.io.CRC32OutputStream; -import htsjdk.samtools.cram.io.CramArray; +import htsjdk.samtools.cram.io.CramIntArray; import htsjdk.samtools.cram.io.CramInt; import htsjdk.samtools.cram.io.ITF8; import htsjdk.samtools.cram.io.LTF8; @@ -49,7 +49,7 @@ public boolean readContainerHeader(final int major, final Container container, f peek[i] = (byte) character; } - container.containerByteSize = CramInt.int32(peek); + container.containerByteSize = CramInt.readInt32(peek); container.sequenceId = ITF8.readUnsignedITF8(inputStream); container.alignmentStart = ITF8.readUnsignedITF8(inputStream); container.alignmentSpan = ITF8.readUnsignedITF8(inputStream); @@ -57,9 +57,9 @@ public boolean readContainerHeader(final int major, final Container container, f container.globalRecordCounter = LTF8.readUnsignedLTF8(inputStream); container.bases = LTF8.readUnsignedLTF8(inputStream); container.blockCount = ITF8.readUnsignedITF8(inputStream); - container.landmarks = CramArray.array(inputStream); + container.landmarks = CramIntArray.array(inputStream); if (major >= 3) - container.checksum = CramInt.int32(inputStream); + container.checksum = CramInt.readInt32(inputStream); return true; } @@ -84,7 +84,7 @@ public int writeContainerHeader(final int major, final Container container, fina length += (LTF8.writeUnsignedLTF8(container.globalRecordCounter, crc32OutputStream) + 7) / 8; length += (LTF8.writeUnsignedLTF8(container.bases, crc32OutputStream) + 7) / 8; length += (ITF8.writeUnsignedITF8(container.blockCount, crc32OutputStream) + 7) / 8; - length += (CramArray.write(container.landmarks, crc32OutputStream) + 7) / 8; + length += (CramIntArray.write(container.landmarks, crc32OutputStream) + 7) / 8; if (major >= 3) { outputStream.write(crc32OutputStream.getCrc32_LittleEndian()); diff --git a/src/main/java/htsjdk/samtools/cram/structure/EncodingParams.java b/src/main/java/htsjdk/samtools/cram/structure/EncodingParams.java index 586fa90fdd..ab568af86e 100644 --- a/src/main/java/htsjdk/samtools/cram/structure/EncodingParams.java +++ b/src/main/java/htsjdk/samtools/cram/structure/EncodingParams.java @@ -18,6 +18,8 @@ package htsjdk.samtools.cram.structure; +import htsjdk.samtools.util.StringUtil; + import java.util.Arrays; public class EncodingParams { @@ -33,7 +35,7 @@ public EncodingParams(final EncodingID id, final byte[] params) { @Override public String toString() { - return id.name() + ":" + javax.xml.bind.DatatypeConverter.printHexBinary(Arrays.copyOfRange(params, 0, Math.max(20, params.length))); + return id.name() + ":" + StringUtil.bytesToHexString(Arrays.copyOfRange(params, 0, Math.max(20, params.length))); } } diff --git a/src/main/java/htsjdk/samtools/cram/structure/SliceIO.java b/src/main/java/htsjdk/samtools/cram/structure/SliceIO.java index 4ccbb36969..3afca735dc 100644 --- a/src/main/java/htsjdk/samtools/cram/structure/SliceIO.java +++ b/src/main/java/htsjdk/samtools/cram/structure/SliceIO.java @@ -22,7 +22,7 @@ import htsjdk.samtools.SAMTagUtil; import htsjdk.samtools.ValidationStringency; import htsjdk.samtools.cram.common.CramVersions; -import htsjdk.samtools.cram.io.CramArray; +import htsjdk.samtools.cram.io.CramIntArray; import htsjdk.samtools.cram.io.ITF8; import htsjdk.samtools.cram.io.InputStreamUtils; import htsjdk.samtools.cram.io.LTF8; @@ -54,7 +54,7 @@ private static void parseSliceHeaderBlock(final int major, final Slice slice) th slice.globalRecordCounter = LTF8.readUnsignedLTF8(inputStream); slice.nofBlocks = ITF8.readUnsignedITF8(inputStream); - slice.contentIDs = CramArray.array(inputStream); + slice.contentIDs = CramIntArray.array(inputStream); slice.embeddedRefBlockContentID = ITF8.readUnsignedITF8(inputStream); slice.refMD5 = new byte[16]; InputStreamUtils.readFully(inputStream, slice.refMD5, 0, slice.refMD5.length); @@ -85,7 +85,7 @@ private static byte[] createSliceHeaderBlockContent(final int major, final Slice int i = 0; for (final int id : slice.external.keySet()) slice.contentIDs[i++] = id; - CramArray.write(slice.contentIDs, byteArrayOutputStream); + CramIntArray.write(slice.contentIDs, byteArrayOutputStream); ITF8.writeUnsignedITF8(slice.embeddedRefBlockContentID, byteArrayOutputStream); byteArrayOutputStream.write(slice.refMD5 == null ? new byte[16] : slice.refMD5); diff --git a/src/main/java/htsjdk/samtools/fastq/FastqEncoder.java b/src/main/java/htsjdk/samtools/fastq/FastqEncoder.java old mode 100644 new mode 100755 index fdbd02dccf..ae181c4294 --- a/src/main/java/htsjdk/samtools/fastq/FastqEncoder.java +++ b/src/main/java/htsjdk/samtools/fastq/FastqEncoder.java @@ -26,9 +26,13 @@ import htsjdk.samtools.SAMException; import htsjdk.samtools.SAMFileHeader; import htsjdk.samtools.SAMRecord; +import htsjdk.samtools.SAMTag; +import htsjdk.samtools.TextTagCodec; import htsjdk.samtools.util.SequenceUtil; import java.io.IOException; +import java.util.Map; +import java.util.function.BiConsumer; /** * Codec for encoding records into FASTQ format. @@ -91,13 +95,27 @@ public static FastqRecord asFastqRecord(final SAMRecord record) { if(record.getReadPairedFlag() && (record.getFirstOfPairFlag() || record.getSecondOfPairFlag())) { readName += (record.getFirstOfPairFlag()) ? FastqConstants.FIRST_OF_PAIR : FastqConstants.SECOND_OF_PAIR; } - return new FastqRecord(readName, record.getReadString(), null, record.getBaseQualityString()); + return new FastqRecord(readName, record.getReadString(), record.getStringAttribute(SAMTag.CO.name()), record.getBaseQualityString()); } /** * Converts a {@link FastqRecord} into a simple unmapped {@link SAMRecord}. */ public static SAMRecord asSAMRecord(final FastqRecord record, final SAMFileHeader header) { + return asSAMRecord(record, header, (s, r) -> {}); + } + + /** + * Converts a {@link FastqRecord} into a simple unmapped {@link SAMRecord}. + * + *

This method allows to pass a {@link BiConsumer} to add the information from the record in + * a customizable manner. + * + * @param record object to encode. + * @param header header for the returned object. + * @param custom function to customize encoding. Note that default information might be overriden. + */ + public static SAMRecord asSAMRecord(final FastqRecord record, final SAMFileHeader header, final BiConsumer custom) { // construct the SAMRecord and set the unmapped flag final SAMRecord samRecord = new SAMRecord(header); samRecord.setReadUnmappedFlag(true); @@ -107,7 +125,25 @@ public static SAMRecord asSAMRecord(final FastqRecord record, final SAMFileHeade samRecord.setReadName(readName); samRecord.setReadBases(record.getReadBases()); samRecord.setBaseQualities(record.getBaseQualities()); + custom.accept(record, samRecord); return samRecord; } + /** + * Encodes the quality header into the comment tag (use in {@link #asSAMRecord(FastqRecord, SAMFileHeader, BiConsumer)}. + * + *

Note that all tabs present in the quality header are replaced by spaces. + */ + public static final BiConsumer QUALITY_HEADER_TO_COMMENT_TAG = (record, samRecord) -> + samRecord.setAttribute(SAMTag.CO.name(), record.getBaseQualityHeader().replaceAll("\t", " ")); + + + public static final BiConsumer QUALITY_HEADER_PARSE_SAM_TAGS = (record, samRecord) -> { + final String[] tokens = record.getBaseQualityHeader().split("\t"); + final TextTagCodec codec = new TextTagCodec(); + for (final String token: tokens) { + final Map.Entry tagValue = codec.decode(token); + samRecord.setAttribute(tagValue.getKey(), tagValue.getValue()); + } + }; } diff --git a/src/main/java/htsjdk/samtools/fastq/FastqRecord.java b/src/main/java/htsjdk/samtools/fastq/FastqRecord.java index 9fbcd39124..4439c0d51b 100755 --- a/src/main/java/htsjdk/samtools/fastq/FastqRecord.java +++ b/src/main/java/htsjdk/samtools/fastq/FastqRecord.java @@ -101,7 +101,7 @@ public String getReadHeader() { /** * Get the read name * - * @return the read name + * @return the read name (may be {@code null}). */ public String getReadName() { return readName; @@ -110,7 +110,7 @@ public String getReadName() { /** * Get the DNA sequence * - * @return read sequence as a string of ACGTN=. + * @return read sequence as a string of ACGTN= (may be {@code null}). */ public String getReadString() { return readString; @@ -128,7 +128,7 @@ public byte[] getReadBases() { /** * Get the base qualities encoded as a FASTQ string * - * @return the quality string + * @return the quality string (may be {@code null}). */ public String getBaseQualityString() { return baseQualityString; @@ -155,7 +155,7 @@ public int getReadLength() { /** * Get the base quality header * - * @return the base quality header + * @return the base quality header (may be {@code null}). */ public String getBaseQualityHeader() { return qualityHeader; @@ -228,7 +228,11 @@ public String toFastQString() { } /** - * Returns {@link #toFastQString()} + * Returns {@link #toFastQString()}. + * + * WARNING: This method will be changed in the future for a simpler representation of the object. + * For code relying on the formatting as a FASTQ String, please refactor your code to use + * {@link #toFastQString()}. */ @Override public String toString() { diff --git a/src/main/java/htsjdk/samtools/reference/AbstractFastaSequenceFile.java b/src/main/java/htsjdk/samtools/reference/AbstractFastaSequenceFile.java index 9c5360c1d6..b815774a68 100644 --- a/src/main/java/htsjdk/samtools/reference/AbstractFastaSequenceFile.java +++ b/src/main/java/htsjdk/samtools/reference/AbstractFastaSequenceFile.java @@ -32,6 +32,7 @@ import htsjdk.samtools.util.IOUtil; import java.io.File; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; @@ -41,6 +42,7 @@ */ abstract class AbstractFastaSequenceFile implements ReferenceSequenceFile { private final Path path; + private final String source; protected SAMSequenceDictionary sequenceDictionary; /** @@ -48,7 +50,7 @@ abstract class AbstractFastaSequenceFile implements ReferenceSequenceFile { * @param file Fasta file to read. Also acts as a prefix for supporting files. */ AbstractFastaSequenceFile(final File file) { - this(file == null ? null : file.toPath()); + this(IOUtil.toPath(file)); } /** @@ -57,20 +59,13 @@ abstract class AbstractFastaSequenceFile implements ReferenceSequenceFile { */ AbstractFastaSequenceFile(final Path path) { this.path = path; + this.source = path == null ? "unknown" : path.toAbsolutePath().toString(); final Path dictionary = findSequenceDictionary(path); if (dictionary != null) { IOUtil.assertFileIsReadable(dictionary); - - try { - final SAMTextHeaderCodec codec = new SAMTextHeaderCodec(); - final BufferedLineReader reader = new BufferedLineReader(Files.newInputStream(dictionary)); - final SAMFileHeader header = codec.decode(reader, - dictionary.toString()); - if (header.getSequenceDictionary() != null && !header.getSequenceDictionary().isEmpty()) { - this.sequenceDictionary = header.getSequenceDictionary(); - } - reader.close(); + try (InputStream dictionaryIn = Files.newInputStream(dictionary)) { + this.sequenceDictionary = ReferenceSequenceFileFactory.loadDictionary(dictionaryIn); } catch (Exception e) { throw new SAMException("Could not open sequence dictionary file: " + dictionary, e); @@ -78,11 +73,20 @@ abstract class AbstractFastaSequenceFile implements ReferenceSequenceFile { } } + /** + * Constructs an {@link AbstractFastaSequenceFile} with an optional sequence dictionary. + * @param path Fasta file to read. Also acts as a prefix for supporting files. + * @param source Named source used for error messages. + * @param sequenceDictionary The sequence dictionary, or null if there isn't one. + */ + AbstractFastaSequenceFile(final Path path, final String source, final SAMSequenceDictionary sequenceDictionary) { + this.path = path; + this.source = source; + this.sequenceDictionary = sequenceDictionary; + } + protected static File findSequenceDictionary(final File file) { - if (file == null) { - return null; - } - Path dictionary = findSequenceDictionary(file.toPath()); + final Path dictionary = findSequenceDictionary(IOUtil.toPath(file)); if (dictionary == null) { return null; } @@ -111,6 +115,11 @@ protected Path getPath() { return path; } + /** Returns the named source of the reference file. */ + protected String getSource() { + return source; + } + /** * Returns the list of sequence records associated with the reference sequence if found * otherwise null. @@ -122,12 +131,15 @@ public SAMSequenceDictionary getSequenceDictionary() { /** Returns the full path to the reference file. */ protected String getAbsolutePath() { + if (path == null) { + return null; + } return path.toAbsolutePath().toString(); } - /** Returns the full path to the reference file. */ + /** Returns the full path to the reference file, or the source if no path was specified. */ public String toString() { - return getAbsolutePath(); + return source; } /** default implementation -- override if index is supported */ @@ -137,13 +149,13 @@ public String toString() { /** default implementation -- override if index is supported */ @Override public ReferenceSequence getSequence( String contig ) { - throw new UnsupportedOperationException("Index does not appear to exist for " + getAbsolutePath() + ". samtools faidx can be used to create an index"); + throw new UnsupportedOperationException("Index does not appear to exist for " + getSource() + ". samtools faidx can be used to create an index"); } /** default implementation -- override if index is supported */ @Override public ReferenceSequence getSubsequenceAt( String contig, long start, long stop ) { - throw new UnsupportedOperationException("Index does not appear to exist for " + getAbsolutePath() + ". samtools faidx can be used to create an index"); + throw new UnsupportedOperationException("Index does not appear to exist for " + getSource() + ". samtools faidx can be used to create an index"); } } diff --git a/src/main/java/htsjdk/samtools/reference/AbstractIndexedFastaSequenceFile.java b/src/main/java/htsjdk/samtools/reference/AbstractIndexedFastaSequenceFile.java new file mode 100644 index 0000000000..331c93bbc7 --- /dev/null +++ b/src/main/java/htsjdk/samtools/reference/AbstractIndexedFastaSequenceFile.java @@ -0,0 +1,247 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017 Daniel Gomez-Sanchez + * + * 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.reference; + +import htsjdk.samtools.Defaults; +import htsjdk.samtools.SAMException; +import htsjdk.samtools.SAMSequenceDictionary; +import htsjdk.samtools.SAMSequenceRecord; +import htsjdk.samtools.util.IOUtil; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; + +/** + * @author Daniel Gomez-Sanchez (magicDGS) + */ +abstract class AbstractIndexedFastaSequenceFile extends AbstractFastaSequenceFile { + + /** + * A representation of the sequence index, stored alongside the fasta in a .fasta.fai file. + */ + private final FastaSequenceIndex index; + + /** + * An iterator into the fasta index, for traversing iteratively across the fasta. + */ + private Iterator indexIterator; + + protected AbstractIndexedFastaSequenceFile(final Path path) throws FileNotFoundException { + this(path, new FastaSequenceIndex(findRequiredFastaIndexFile(path))); + } + + protected AbstractIndexedFastaSequenceFile(final Path path, final FastaSequenceIndex index) { + super(path); + if (index == null) { + throw new IllegalArgumentException("Null index for fasta " + path); + } + this.index = index; + IOUtil.assertFileIsReadable(path); + reset(); + if(getSequenceDictionary() != null) { + sanityCheckDictionaryAgainstIndex(path.toAbsolutePath().toString(),sequenceDictionary,index); + } + } + + /** + * Initialise the given indexed fasta sequence file stream. + * @param source The named source of the reference file (used in error messages). + * @param index The fasta index. + * @param dictionary The sequence dictionary, or null if there isn't one. + */ + protected AbstractIndexedFastaSequenceFile(String source, final FastaSequenceIndex index, SAMSequenceDictionary dictionary) { + super(null, source, dictionary); + this.index = index; + reset(); + } + + protected static Path findRequiredFastaIndexFile(Path fastaFile) throws FileNotFoundException { + Path ret = findFastaIndex(fastaFile); + if (ret == null) throw new FileNotFoundException(ReferenceSequenceFileFactory.getFastaIndexFileName(fastaFile) + " not found."); + return ret; + } + + protected static Path findFastaIndex(Path fastaFile) { + Path indexFile = ReferenceSequenceFileFactory.getFastaIndexFileName(fastaFile); + if (!Files.exists(indexFile)) return null; + return indexFile; + } + + /** + * Do some basic checking to make sure the dictionary and the index match. + * @param fastaFile Used for error reporting only. + * @param sequenceDictionary sequence dictionary to check against the index. + * @param index index file to check against the dictionary. + */ + protected static void sanityCheckDictionaryAgainstIndex(final String fastaFile, + final SAMSequenceDictionary sequenceDictionary, + final FastaSequenceIndex index) { + // Make sure dictionary and index are the same size. + if( sequenceDictionary.getSequences().size() != index.size() ) + throw new SAMException("Sequence dictionary and index contain different numbers of contigs"); + + Iterator sequenceIterator = sequenceDictionary.getSequences().iterator(); + Iterator indexIterator = index.iterator(); + + while(sequenceIterator.hasNext() && indexIterator.hasNext()) { + SAMSequenceRecord sequenceEntry = sequenceIterator.next(); + FastaSequenceIndexEntry indexEntry = indexIterator.next(); + + if(!sequenceEntry.getSequenceName().equals(indexEntry.getContig())) { + throw new SAMException(String.format("Mismatch between sequence dictionary fasta index for %s, sequence '%s' != '%s'.", + fastaFile, sequenceEntry.getSequenceName(),indexEntry.getContig())); + } + + // Make sure sequence length matches index length. + if( sequenceEntry.getSequenceLength() != indexEntry.getSize()) + throw new SAMException("Index length does not match dictionary length for contig: " + sequenceEntry.getSequenceName() ); + } + } + + public FastaSequenceIndex getIndex() { + return index; + } + + /** + * Gets the next sequence if available, or null if not present. + * @return next sequence if available, or null if not present. + */ + @Override + public ReferenceSequence nextSequence() { + if( !indexIterator.hasNext() ) + return null; + return getSequence( indexIterator.next().getContig() ); + } + + /** + * Reset the iterator over the index. + */ + @Override + public void reset() { + indexIterator = index.iterator(); + } + + @Override + public final boolean isIndexed() { + return true; + } + + /** + * Retrieves the complete sequence described by this contig. + * @param contig contig whose data should be returned. + * @return The full sequence associated with this contig. + */ + @Override + public ReferenceSequence getSequence( String contig ) { + return getSubsequenceAt( contig, 1, (int)index.getIndexEntry(contig).getSize() ); + } + + /** + * Gets the subsequence of the contig in the range [start,stop] + * @param contig Contig whose subsequence to retrieve. + * @param start inclusive, 1-based start of region. + * @param stop inclusive, 1-based stop of region. + * @return The partial reference sequence associated with this range. + */ + @Override + public ReferenceSequence getSubsequenceAt( String contig, long start, long stop ) { + if(start > stop + 1) + throw new SAMException(String.format("Malformed query; start point %d lies after end point %d",start,stop)); + + FastaSequenceIndexEntry indexEntry = getIndex().getIndexEntry(contig); + + if(stop > indexEntry.getSize()) + throw new SAMException("Query asks for data past end of contig"); + + int length = (int)(stop - start + 1); + + byte[] target = new byte[length]; + ByteBuffer targetBuffer = ByteBuffer.wrap(target); + + final int basesPerLine = indexEntry.getBasesPerLine(); + final int bytesPerLine = indexEntry.getBytesPerLine(); + final int terminatorLength = bytesPerLine - basesPerLine; + + long startOffset = ((start-1)/basesPerLine)*bytesPerLine + (start-1)%basesPerLine; + // Cast to long so the second argument cannot overflow a signed integer. + final long minBufferSize = Math.min((long) Defaults.NON_ZERO_BUFFER_SIZE, (long)(length / basesPerLine + 2) * (long)bytesPerLine); + if (minBufferSize > Integer.MAX_VALUE) throw new SAMException("Buffer is too large: " + minBufferSize); + + // Allocate a buffer for reading in sequence data. + final ByteBuffer channelBuffer = ByteBuffer.allocate((int)minBufferSize); + + while(targetBuffer.position() < length) { + // If the bufferOffset is currently within the eol characters in the string, push the bufferOffset forward to the next printable character. + startOffset += Math.max((int)(startOffset%bytesPerLine - basesPerLine + 1),0); + + try { + startOffset += readFromPosition(channelBuffer, indexEntry.getLocation()+startOffset); + } + catch(IOException ex) { + throw new SAMException("Unable to load " + contig + "(" + start + ", " + stop + ") from " + getSource(), ex); + } + + // Reset the buffer for outbound transfers. + channelBuffer.flip(); + + // Calculate the size of the next run of bases based on the contents we've already retrieved. + final int positionInContig = (int)start-1+targetBuffer.position(); + final int nextBaseSpan = Math.min(basesPerLine-positionInContig%basesPerLine,length-targetBuffer.position()); + // Cap the bytes to transfer by limiting the nextBaseSpan to the size of the channel buffer. + int bytesToTransfer = Math.min(nextBaseSpan,channelBuffer.capacity()); + + channelBuffer.limit(channelBuffer.position()+bytesToTransfer); + + while(channelBuffer.hasRemaining()) { + targetBuffer.put(channelBuffer); + + bytesToTransfer = Math.min(basesPerLine,length-targetBuffer.position()); + channelBuffer.limit(Math.min(channelBuffer.position()+bytesToTransfer+terminatorLength,channelBuffer.capacity())); + channelBuffer.position(Math.min(channelBuffer.position()+terminatorLength,channelBuffer.capacity())); + } + + // Reset the buffer for inbound transfers. + channelBuffer.flip(); + } + + return new ReferenceSequence( contig, indexEntry.getSequenceIndex(), target ); + } + + /** + * Reads a sequence of bytes from this sequence file into the given buffer, + * starting at the given file position. + * + * @param buffer the buffer into which bytes are to be transferred + * @param position the position to start reading at + * + * @return the number of bytes read + * @throws IOException if an I/O error occurs while reading + */ + protected abstract int readFromPosition(final ByteBuffer buffer, long position) throws IOException; +} diff --git a/src/main/java/htsjdk/samtools/reference/BlockCompressedIndexedFastaSequenceFile.java b/src/main/java/htsjdk/samtools/reference/BlockCompressedIndexedFastaSequenceFile.java new file mode 100644 index 0000000000..43aff7126f --- /dev/null +++ b/src/main/java/htsjdk/samtools/reference/BlockCompressedIndexedFastaSequenceFile.java @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017 Daniel Gomez-Sanchez + * + * 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.reference; + +import htsjdk.samtools.SAMException; +import htsjdk.samtools.seekablestream.SeekablePathStream; +import htsjdk.samtools.util.BlockCompressedInputStream; +import htsjdk.samtools.util.GZIIndex; +import htsjdk.samtools.util.IOUtil; + +import java.io.BufferedInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * A block-compressed FASTA file driven by an index for fast lookups. + * + *

Supports two interfaces: the ReferenceSequenceFile for old-style, stateful lookups and a direct getter. + * + * @author Daniel Gomez-Sanchez (magicDGS) + */ +public class BlockCompressedIndexedFastaSequenceFile extends AbstractIndexedFastaSequenceFile { + + private final BlockCompressedInputStream stream; + private final GZIIndex gzindex; + + public BlockCompressedIndexedFastaSequenceFile(final Path path) + throws FileNotFoundException { + this(path,new FastaSequenceIndex((findRequiredFastaIndexFile(path)))); + } + + public BlockCompressedIndexedFastaSequenceFile(final Path path, final FastaSequenceIndex index) { + this(path, index, loadFastaGziIndex(path)); + } + + public BlockCompressedIndexedFastaSequenceFile(final Path path, final FastaSequenceIndex index, final GZIIndex gziIndex) { + super(path, index); + if (gziIndex == null) { + throw new IllegalArgumentException("null gzi index"); + } + if (!canCreateBlockCompresedIndexedFastaSequence(path)) { + throw new SAMException("Invalid block-compressed Fasta file"); + } + try { + stream = new BlockCompressedInputStream(new SeekablePathStream(path)); + gzindex = gziIndex; + } catch (IOException e) { + throw new SAMException("Fasta file should be readable but is not: " + path, e); + } + } + + private static GZIIndex loadFastaGziIndex(final Path path) { + try { + return GZIIndex.loadIndex(GZIIndex.resolveIndexNameForBgzipFile(path)); + } catch (final IOException e) { + throw new SAMException("Error loading GZI index for " + path, e); + } + } + + private static boolean canCreateBlockCompresedIndexedFastaSequence(final Path path) { + try { + // check if the it is a valid block-compressed file and if the .gzi index exits + return IOUtil.isBlockCompressed(path, true) && Files.exists(GZIIndex.resolveIndexNameForBgzipFile(path)); + } catch (IOException e) { + return false; + } + } + + @Override + protected int readFromPosition(final ByteBuffer buffer, final long position) throws IOException { + // old position to get back + final long oldPos = stream.getFilePointer(); + try { + final long virtualOffset = gzindex.getVirtualOffsetForSeek(position); + stream.seek(virtualOffset); + final byte[] array = new byte[buffer.remaining()]; + final int read = stream.read(array); + buffer.put(array); + return read; + } finally { + stream.seek(oldPos); + } + } + + @Override + public void close() throws IOException { + stream.close(); + } +} diff --git a/src/main/java/htsjdk/samtools/reference/FastaSequenceFile.java b/src/main/java/htsjdk/samtools/reference/FastaSequenceFile.java index 744d797732..3dc8fd191f 100644 --- a/src/main/java/htsjdk/samtools/reference/FastaSequenceFile.java +++ b/src/main/java/htsjdk/samtools/reference/FastaSequenceFile.java @@ -26,12 +26,15 @@ import htsjdk.samtools.Defaults; import htsjdk.samtools.SAMException; +import htsjdk.samtools.SAMSequenceDictionary; import htsjdk.samtools.SAMSequenceRecord; +import htsjdk.samtools.seekablestream.SeekableStream; import htsjdk.samtools.util.FastLineReader; import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.StringUtil; import java.io.File; +import java.io.IOException; import java.nio.file.Path; /** @@ -42,6 +45,7 @@ public class FastaSequenceFile extends AbstractFastaSequenceFile { private final boolean truncateNamesAtWhitespace; + private final SeekableStream seekableStream; private FastLineReader in; private int sequenceIndex = -1; private final byte[] basesBuffer = new byte[Defaults.NON_ZERO_BUFFER_SIZE]; @@ -49,16 +53,28 @@ public class FastaSequenceFile extends AbstractFastaSequenceFile { /** Constructs a FastaSequenceFile that reads from the specified file. */ public FastaSequenceFile(final File file, final boolean truncateNamesAtWhitespace) { - this(file == null ? null : file.toPath(), truncateNamesAtWhitespace); + this(IOUtil.toPath(file), truncateNamesAtWhitespace); } /** Constructs a FastaSequenceFile that reads from the specified file. */ public FastaSequenceFile(final Path path, final boolean truncateNamesAtWhitespace) { super(path); this.truncateNamesAtWhitespace = truncateNamesAtWhitespace; + this.seekableStream = null; this.in = new FastLineReader(IOUtil.openFileForReading(path)); } + /** + * Constructs a FastaSequenceFile that reads from the specified stream (which must not be compressed, i.e. + * the caller is responsible for decompressing the stream). + */ + public FastaSequenceFile(String source, final SeekableStream seekableStream, SAMSequenceDictionary dictionary, final boolean truncateNamesAtWhitespace) { + super(null, source, dictionary); + this.truncateNamesAtWhitespace = truncateNamesAtWhitespace; + this.seekableStream = seekableStream; + this.in = new FastLineReader(seekableStream); + } + /** * It's good to call this to free up memory. */ @@ -88,9 +104,17 @@ public ReferenceSequence nextSequence() { @Override public void reset() { this.sequenceIndex = -1; - this.in.close(); - this.in = new FastLineReader(IOUtil.openFileForReading(getPath())); - + if (getPath() != null) { + this.in.close(); + this.in = new FastLineReader(IOUtil.openFileForReading(getPath())); + } else { + try { + this.seekableStream.seek(0); + } catch (IOException e) { + throw new SAMException("Problem seeking to start of stream during reset", e); + } + this.in = new FastLineReader(this.seekableStream); + } } private String readSequenceName() { @@ -100,7 +124,7 @@ private String readSequenceName() { } final byte b = in.getByte(); if (b != '>') { - throw new SAMException("Format exception reading FASTA " + getAbsolutePath() + ". Expected > but saw chr(" + + throw new SAMException("Format exception reading FASTA " + getSource() + ". Expected > but saw chr(" + b + ") at start of sequence with index " + this.sequenceIndex); } final byte[] nameBuffer = new byte[4096]; @@ -111,11 +135,11 @@ private String readSequenceName() { } nameLength += in.readToEndOfOutputBufferOrEoln(nameBuffer, nameLength); if (nameLength == nameBuffer.length && !in.atEoln()) { - throw new SAMException("Sequence name too long in FASTA " + getAbsolutePath()); + throw new SAMException("Sequence name too long in FASTA " + getSource()); } } while (!in.atEoln()); if (nameLength == 0) { - throw new SAMException("Missing sequence name in FASTA " + getAbsolutePath()); + throw new SAMException("Missing sequence name in FASTA " + getSource()); } String name = StringUtil.bytesToString(nameBuffer, 0, nameLength).trim(); if (truncateNamesAtWhitespace) { diff --git a/src/main/java/htsjdk/samtools/reference/FastaSequenceIndex.java b/src/main/java/htsjdk/samtools/reference/FastaSequenceIndex.java index 3668fe6718..8a3f9da09e 100644 --- a/src/main/java/htsjdk/samtools/reference/FastaSequenceIndex.java +++ b/src/main/java/htsjdk/samtools/reference/FastaSequenceIndex.java @@ -31,6 +31,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.nio.file.Files; @@ -56,7 +57,7 @@ public class FastaSequenceIndex implements Iterable { * @throws FileNotFoundException if the index file cannot be found. */ public FastaSequenceIndex( File indexFile ) { - this(indexFile == null ? null : indexFile.toPath()); + this(IOUtil.toPath(indexFile)); } /** @@ -66,7 +67,19 @@ public FastaSequenceIndex( File indexFile ) { */ public FastaSequenceIndex( Path indexFile ) { IOUtil.assertFileIsReadable(indexFile); - parseIndexFile(indexFile); + try (InputStream in = Files.newInputStream(indexFile)) { + parseIndexFile(in); + } catch (IOException e) { + throw new SAMException("Fasta index file could not be opened: " + indexFile, e); + } + } + + /** + * Build a sequence index from the specified input stream. + * @param in InputStream to read from. + */ + public FastaSequenceIndex(InputStream in) { + parseIndexFile(in); } /** @@ -124,12 +137,10 @@ public boolean equals(Object other) { /** * Parse the contents of an index file, caching the results internally. - * @param indexFile File to parse. - * @throws IOException Thrown if file could not be opened. + * @param in InputStream to parse. */ - private void parseIndexFile(Path indexFile) { - try { - Scanner scanner = new Scanner(indexFile); + private void parseIndexFile(InputStream in) { + try (Scanner scanner = new Scanner(in)) { int sequenceIndex = 0; while( scanner.hasNext() ) { // Tokenize and validate the index line. @@ -154,10 +165,6 @@ private void parseIndexFile(Path indexFile) { // Build sequence structure add(new FastaSequenceIndexEntry(contig,location,size,basesPerLine,bytesPerLine, sequenceIndex++) ); } - scanner.close(); - } catch (IOException e) { - throw new SAMException("Fasta index file could not be opened: " + indexFile, e); - } } @@ -221,128 +228,3 @@ public int size() { return sequenceEntries.size(); } } - -/** - * Hold an individual entry in a fasta sequence index file. - */ -class FastaSequenceIndexEntry { - private String contig; - private long location; - private long size; - private int basesPerLine; - private int bytesPerLine; - private final int sequenceIndex; - - /** - * Create a new entry with the given parameters. - * @param contig Contig this entry represents. - * @param location Location (byte coordinate) in the fasta file. - * @param size The number of bases in the contig. - * @param basesPerLine How many bases are on each line. - * @param bytesPerLine How many bytes are on each line (includes newline characters). - */ - public FastaSequenceIndexEntry( String contig, - long location, - long size, - int basesPerLine, - int bytesPerLine, - int sequenceIndex) { - this.contig = contig; - this.location = location; - this.size = size; - this.basesPerLine = basesPerLine; - this.bytesPerLine = bytesPerLine; - this.sequenceIndex = sequenceIndex; - } - - /** - * Gets the contig associated with this entry. - * @return String representation of the contig. - */ - public String getContig() { - return contig; - } - - /** - * Sometimes contigs need to be adjusted on-the-fly to - * match sequence dictionary entries. Provide that capability - * to other classes w/i the package. - * @param contig New value for the contig. - */ - protected void setContig(String contig) { - this.contig = contig; - } - - /** - * Gets the location of this contig within the fasta. - * @return seek position within the fasta. - */ - public long getLocation() { - return location; - } - - /** - * Gets the size, in bytes, of the data in the contig. - * @return size of the contig bases in bytes. - */ - public long getSize() { - return size; - } - - /** - * Gets the number of bases in a given line. - * @return Number of bases in the fasta line. - */ - public int getBasesPerLine() { - return basesPerLine; - } - - /** - * How many bytes (bases + whitespace) are consumed by the - * given line? - * @return Number of bytes in a line. - */ - public int getBytesPerLine() { - return bytesPerLine; - } - - public int getSequenceIndex() { - return sequenceIndex; - } - - /** - * For debugging. Emit the contents of each contig line. - * @return A string representation of the contig line. - */ - public String toString() { - return String.format("contig %s; location %d; size %d; basesPerLine %d; bytesPerLine %d", contig, - location, - size, - basesPerLine, - bytesPerLine ); - } - - /** - * Compare this index entry to another index entry. - * @param other another FastaSequenceIndexEntry - * @return True if each has the same name, location, size, basesPerLine and bytesPerLine - */ - public boolean equals(Object other) { - if(!(other instanceof FastaSequenceIndexEntry)) - return false; - - if (this == other) return true; - - FastaSequenceIndexEntry otherEntry = (FastaSequenceIndexEntry)other; - return (contig.equals(otherEntry.contig) && size == otherEntry.size && location == otherEntry.location - && basesPerLine == otherEntry.basesPerLine && bytesPerLine == otherEntry.bytesPerLine); - } - - /** - * In general, we expect one entry per contig, so compute the hash based only on the contig. - * @return A unique hash code representing this object. - */ - public int hashCode() { - return contig.hashCode(); - } -} diff --git a/src/main/java/htsjdk/samtools/reference/FastaSequenceIndexEntry.java b/src/main/java/htsjdk/samtools/reference/FastaSequenceIndexEntry.java new file mode 100644 index 0000000000..f8bbf4e157 --- /dev/null +++ b/src/main/java/htsjdk/samtools/reference/FastaSequenceIndexEntry.java @@ -0,0 +1,150 @@ +/* + * 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.reference; + +/** + * Hold an individual entry in a fasta sequence index file. + */ +public class FastaSequenceIndexEntry { + private String contig; + private long location; + private long size; + private int basesPerLine; + private int bytesPerLine; + private final int sequenceIndex; + + /** + * Create a new entry with the given parameters. + * @param contig Contig this entry represents. + * @param location Location (byte coordinate) in the fasta file. + * @param size The number of bases in the contig. + * @param basesPerLine How many bases are on each line. + * @param bytesPerLine How many bytes are on each line (includes newline characters). + */ + public FastaSequenceIndexEntry( String contig, + long location, + long size, + int basesPerLine, + int bytesPerLine, + int sequenceIndex) { + this.contig = contig; + this.location = location; + this.size = size; + this.basesPerLine = basesPerLine; + this.bytesPerLine = bytesPerLine; + this.sequenceIndex = sequenceIndex; + } + + /** + * Gets the contig associated with this entry. + * @return String representation of the contig. + */ + public String getContig() { + return contig; + } + + /** + * Sometimes contigs need to be adjusted on-the-fly to + * match sequence dictionary entries. Provide that capability + * to other classes w/i the package. + * @param contig New value for the contig. + */ + protected void setContig(String contig) { + this.contig = contig; + } + + /** + * Gets the location of this contig within the fasta. + * @return seek position within the fasta. + */ + public long getLocation() { + return location; + } + + /** + * Gets the size, in bytes, of the data in the contig. + * @return size of the contig bases in bytes. + */ + public long getSize() { + return size; + } + + /** + * Gets the number of bases in a given line. + * @return Number of bases in the fasta line. + */ + public int getBasesPerLine() { + return basesPerLine; + } + + /** + * How many bytes (bases + whitespace) are consumed by the + * given line? + * @return Number of bytes in a line. + */ + public int getBytesPerLine() { + return bytesPerLine; + } + + public int getSequenceIndex() { + return sequenceIndex; + } + + /** + * For debugging. Emit the contents of each contig line. + * @return A string representation of the contig line. + */ + public String toString() { + return String.format("contig %s; location %d; size %d; basesPerLine %d; bytesPerLine %d", contig, + location, + size, + basesPerLine, + bytesPerLine ); + } + + /** + * Compare this index entry to another index entry. + * @param other another FastaSequenceIndexEntry + * @return True if each has the same name, location, size, basesPerLine and bytesPerLine + */ + public boolean equals(Object other) { + if(!(other instanceof FastaSequenceIndexEntry)) + return false; + + if (this == other) return true; + + FastaSequenceIndexEntry otherEntry = (FastaSequenceIndexEntry)other; + return (contig.equals(otherEntry.contig) && size == otherEntry.size && location == otherEntry.location + && basesPerLine == otherEntry.basesPerLine && bytesPerLine == otherEntry.bytesPerLine); + } + + /** + * In general, we expect one entry per contig, so compute the hash based only on the contig. + * @return A unique hash code representing this object. + */ + public int hashCode() { + return contig.hashCode(); + } +} diff --git a/src/main/java/htsjdk/samtools/reference/IndexedFastaSequenceFile.java b/src/main/java/htsjdk/samtools/reference/IndexedFastaSequenceFile.java index 5c318782e1..226d539c0b 100644 --- a/src/main/java/htsjdk/samtools/reference/IndexedFastaSequenceFile.java +++ b/src/main/java/htsjdk/samtools/reference/IndexedFastaSequenceFile.java @@ -24,44 +24,34 @@ package htsjdk.samtools.reference; -import htsjdk.samtools.Defaults; import htsjdk.samtools.SAMException; import htsjdk.samtools.SAMSequenceDictionary; -import htsjdk.samtools.SAMSequenceRecord; +import htsjdk.samtools.seekablestream.ReadableSeekableStreamByteChannel; +import htsjdk.samtools.seekablestream.SeekableStream; +import htsjdk.samtools.util.BlockCompressedInputStream; import htsjdk.samtools.util.IOUtil; -import java.io.Closeable; +import java.io.BufferedInputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.SeekableByteChannel; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Iterator; /** * A fasta file driven by an index for fast, concurrent lookups. Supports two interfaces: * the ReferenceSequenceFile for old-style, stateful lookups and a direct getter. */ -public class IndexedFastaSequenceFile extends AbstractFastaSequenceFile implements Closeable { +public class IndexedFastaSequenceFile extends AbstractIndexedFastaSequenceFile { /** * The interface facilitating direct access to the fasta. */ private final SeekableByteChannel channel; - /** - * A representation of the sequence index, stored alongside the fasta in a .fasta.fai file. - */ - private final FastaSequenceIndex index; - - /** - * An iterator into the fasta index, for traversing iteratively across the fasta. - */ - private Iterator indexIterator; - /** * Open the given indexed fasta sequence file. Throw an exception if the file cannot be opened. * @param file The file to open. @@ -69,7 +59,7 @@ public class IndexedFastaSequenceFile extends AbstractFastaSequenceFile implemen * @throws FileNotFoundException If the fasta or any of its supporting files cannot be found. */ public IndexedFastaSequenceFile(final File file, final FastaSequenceIndex index) { - this(file == null ? null : file.toPath(), index); + this(IOUtil.toPath(file), index); } /** @@ -78,7 +68,7 @@ public IndexedFastaSequenceFile(final File file, final FastaSequenceIndex index) * @throws FileNotFoundException If the fasta or any of its supporting files cannot be found. */ public IndexedFastaSequenceFile(final File file) throws FileNotFoundException { - this(file, new FastaSequenceIndex((findRequiredFastaIndexFile(file)))); + this(file, new FastaSequenceIndex((findRequiredFastaIndexFile(IOUtil.toPath(file))))); } /** @@ -87,19 +77,16 @@ public IndexedFastaSequenceFile(final File file) throws FileNotFoundException { * @param index Pre-built FastaSequenceIndex, for the case in which one does not exist on disk. */ public IndexedFastaSequenceFile(final Path path, final FastaSequenceIndex index) { - super(path); - if (index == null) throw new IllegalArgumentException("Null index for fasta " + path); - this.index = index; - IOUtil.assertFileIsReadable(path); + super(path, index); try { + // check if the it is a valid block-compressed file + if (IOUtil.isBlockCompressed(path, true)) { + throw new SAMException("Indexed block-compressed FASTA file cannot be handled: " + path); + } this.channel = Files.newByteChannel(path); } catch (IOException e) { - throw new SAMException("Fasta file should be readable but is not: " + path, e); + throw new SAMException("FASTA file should be readable but is not: " + path, e); } - reset(); - - if(getSequenceDictionary() != null) - sanityCheckDictionaryAgainstIndex(path.toAbsolutePath().toString(),sequenceDictionary,index); } /** @@ -111,178 +98,52 @@ public IndexedFastaSequenceFile(final Path path) throws FileNotFoundException { this(path, new FastaSequenceIndex((findRequiredFastaIndexFile(path)))); } - @Override - public boolean isIndexed() {return true;} - - private static File findFastaIndex(File fastaFile) { - File indexFile = getFastaIndexFileName(fastaFile); - if (!indexFile.exists()) return null; - return indexFile; - } - - private static File getFastaIndexFileName(File fastaFile) { - return new File(fastaFile.getAbsolutePath() + ".fai"); - } - - private static File findRequiredFastaIndexFile(File fastaFile) throws FileNotFoundException { - File ret = findFastaIndex(fastaFile); - if (ret == null) throw new FileNotFoundException(getFastaIndexFileName(fastaFile) + " not found."); - return ret; - } - - public static boolean canCreateIndexedFastaReader(final File fastaFile) { - return (fastaFile.exists() && - findFastaIndex(fastaFile) != null); - } - - private static Path findFastaIndex(Path fastaFile) { - Path indexFile = ReferenceSequenceFileFactory.getFastaIndexFileName(fastaFile); - if (!Files.exists(indexFile)) return null; - return indexFile; - } - - private static Path findRequiredFastaIndexFile(Path fastaFile) throws FileNotFoundException { - Path ret = findFastaIndex(fastaFile); - if (ret == null) throw new FileNotFoundException(ReferenceSequenceFileFactory.getFastaIndexFileName(fastaFile) + " not found."); - return ret; - } - - public static boolean canCreateIndexedFastaReader(final Path fastaFile) { - return (Files.exists(fastaFile) && - findFastaIndex(fastaFile) != null); - } - /** - * Do some basic checking to make sure the dictionary and the index match. - * @param fastaFile Used for error reporting only. - * @param sequenceDictionary sequence dictionary to check against the index. - * @param index index file to check against the dictionary. + * Initialise the given indexed fasta sequence file stream. + * @param source The named source of the reference file (used in error messages). + * @param in The input stream to read the fasta file from. + * @param index The fasta index. + * @param dictionary The sequence dictionary, or null if there isn't one. */ - protected static void sanityCheckDictionaryAgainstIndex(final String fastaFile, - final SAMSequenceDictionary sequenceDictionary, - final FastaSequenceIndex index) { - // Make sure dictionary and index are the same size. - if( sequenceDictionary.getSequences().size() != index.size() ) - throw new SAMException("Sequence dictionary and index contain different numbers of contigs"); - - Iterator sequenceIterator = sequenceDictionary.getSequences().iterator(); - Iterator indexIterator = index.iterator(); - - while(sequenceIterator.hasNext() && indexIterator.hasNext()) { - SAMSequenceRecord sequenceEntry = sequenceIterator.next(); - FastaSequenceIndexEntry indexEntry = indexIterator.next(); - - if(!sequenceEntry.getSequenceName().equals(indexEntry.getContig())) { - throw new SAMException(String.format("Mismatch between sequence dictionary fasta index for %s, sequence '%s' != '%s'.", - fastaFile, sequenceEntry.getSequenceName(),indexEntry.getContig())); - } - - // Make sure sequence length matches index length. - if( sequenceEntry.getSequenceLength() != indexEntry.getSize()) - throw new SAMException("Index length does not match dictionary length for contig: " + sequenceEntry.getSequenceName() ); - } + public IndexedFastaSequenceFile(String source, final SeekableStream in, final FastaSequenceIndex index, SAMSequenceDictionary dictionary) { + super(source, index, dictionary); + this.channel = new ReadableSeekableStreamByteChannel(in); } /** - * Retrieves the sequence dictionary for the fasta file. - * @return sequence dictionary of the fasta. + * @deprecated use {@link ReferenceSequenceFileFactory#canCreateIndexedFastaReader(Path)} instead. */ - @Override - public SAMSequenceDictionary getSequenceDictionary() { - return sequenceDictionary; - } - - /** - * Retrieves the complete sequence described by this contig. - * @param contig contig whose data should be returned. - * @return The full sequence associated with this contig. - */ - @Override - public ReferenceSequence getSequence( String contig ) { - return getSubsequenceAt( contig, 1, (int)index.getIndexEntry(contig).getSize() ); + @Deprecated + public static boolean canCreateIndexedFastaReader(final File fastaFile) { + return canCreateIndexedFastaReader(fastaFile.toPath()); } /** - * Gets the subsequence of the contig in the range [start,stop] - * @param contig Contig whose subsequence to retrieve. - * @param start inclusive, 1-based start of region. - * @param stop inclusive, 1-based stop of region. - * @return The partial reference sequence associated with this range. + * @deprecated use {@link ReferenceSequenceFileFactory#canCreateIndexedFastaReader(Path)} instead. */ - @Override - public ReferenceSequence getSubsequenceAt( String contig, long start, long stop ) { - if(start > stop + 1) - throw new SAMException(String.format("Malformed query; start point %d lies after end point %d",start,stop)); - - FastaSequenceIndexEntry indexEntry = index.getIndexEntry(contig); - - if(stop > indexEntry.getSize()) - throw new SAMException("Query asks for data past end of contig"); - - int length = (int)(stop - start + 1); - - byte[] target = new byte[length]; - ByteBuffer targetBuffer = ByteBuffer.wrap(target); - - final int basesPerLine = indexEntry.getBasesPerLine(); - final int bytesPerLine = indexEntry.getBytesPerLine(); - final int terminatorLength = bytesPerLine - basesPerLine; - - long startOffset = ((start-1)/basesPerLine)*bytesPerLine + (start-1)%basesPerLine; - // Cast to long so the second argument cannot overflow a signed integer. - final long minBufferSize = Math.min((long) Defaults.NON_ZERO_BUFFER_SIZE, (long)(length / basesPerLine + 2) * (long)bytesPerLine); - if (minBufferSize > Integer.MAX_VALUE) throw new SAMException("Buffer is too large: " + minBufferSize); - - // Allocate a buffer for reading in sequence data. - final ByteBuffer channelBuffer = ByteBuffer.allocate((int)minBufferSize); - - while(targetBuffer.position() < length) { - // If the bufferOffset is currently within the eol characters in the string, push the bufferOffset forward to the next printable character. - startOffset += Math.max((int)(startOffset%bytesPerLine - basesPerLine + 1),0); - - try { - startOffset += readFromPosition(channel, channelBuffer, indexEntry.getLocation()+startOffset); - } - catch(IOException ex) { - throw new SAMException("Unable to load " + contig + "(" + start + ", " + stop + ") from " + getAbsolutePath(), ex); - } - - // Reset the buffer for outbound transfers. - channelBuffer.flip(); - - // Calculate the size of the next run of bases based on the contents we've already retrieved. - final int positionInContig = (int)start-1+targetBuffer.position(); - final int nextBaseSpan = Math.min(basesPerLine-positionInContig%basesPerLine,length-targetBuffer.position()); - // Cap the bytes to transfer by limiting the nextBaseSpan to the size of the channel buffer. - int bytesToTransfer = Math.min(nextBaseSpan,channelBuffer.capacity()); - - channelBuffer.limit(channelBuffer.position()+bytesToTransfer); - - while(channelBuffer.hasRemaining()) { - targetBuffer.put(channelBuffer); - - bytesToTransfer = Math.min(basesPerLine,length-targetBuffer.position()); - channelBuffer.limit(Math.min(channelBuffer.position()+bytesToTransfer+terminatorLength,channelBuffer.capacity())); - channelBuffer.position(Math.min(channelBuffer.position()+terminatorLength,channelBuffer.capacity())); + @Deprecated + public static boolean canCreateIndexedFastaReader(final Path fastaFile) { + try { + if (IOUtil.isBlockCompressed(fastaFile, true)) { + return false; } - - // Reset the buffer for inbound transfers. - channelBuffer.flip(); + return (Files.exists(fastaFile) && + findFastaIndex(fastaFile) != null); + } catch (IOException e) { + return false; } - - return new ReferenceSequence( contig, indexEntry.getSequenceIndex(), target ); } /** * Reads a sequence of bytes from this channel into the given buffer, * starting at the given file position. - * @param channel the channel to read from * @param buffer the buffer into which bytes are to be transferred * @param position the position to start reading at * @return the number of bytes read * @throws IOException if an I/O error occurs while reading */ - private static int readFromPosition(final SeekableByteChannel channel, final ByteBuffer buffer, long position) throws IOException { + @Override + protected int readFromPosition(final ByteBuffer buffer, long position) throws IOException { if (channel instanceof FileChannel) { // special case to take advantage of native code path return ((FileChannel) channel).read(buffer,position); } else { @@ -296,33 +157,6 @@ private static int readFromPosition(final SeekableByteChannel channel, final Byt } } - /** - * Gets the next sequence if available, or null if not present. - * @return next sequence if available, or null if not present. - */ - @Override - public ReferenceSequence nextSequence() { - if( !indexIterator.hasNext() ) - return null; - return getSequence( indexIterator.next().getContig() ); - } - - /** - * Reset the iterator over the index. - */ - @Override - public void reset() { - indexIterator = index.iterator(); - } - - /** - * A simple toString implementation for debugging. - * @return String representation of the file. - */ - public String toString() { - return getAbsolutePath(); - } - @Override public void close() throws IOException { channel.close(); diff --git a/src/main/java/htsjdk/samtools/reference/ReferenceSequenceFileFactory.java b/src/main/java/htsjdk/samtools/reference/ReferenceSequenceFileFactory.java index 654706819d..d013d56b44 100644 --- a/src/main/java/htsjdk/samtools/reference/ReferenceSequenceFileFactory.java +++ b/src/main/java/htsjdk/samtools/reference/ReferenceSequenceFileFactory.java @@ -24,10 +24,22 @@ package htsjdk.samtools.reference; +import htsjdk.samtools.SAMException; +import htsjdk.samtools.util.BlockCompressedInputStream; +import htsjdk.samtools.util.GZIIndex; +import htsjdk.samtools.SAMFileHeader; +import htsjdk.samtools.SAMSequenceDictionary; +import htsjdk.samtools.SAMTextHeaderCodec; +import htsjdk.samtools.seekablestream.SeekableStream; +import htsjdk.samtools.util.BufferedLineReader; import htsjdk.samtools.util.IOUtil; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; import java.nio.file.Path; import java.util.HashSet; import java.util.Set; @@ -81,7 +93,7 @@ public static ReferenceSequenceFile getReferenceSequenceFile(final File file, fi * @param preferIndexed if true attempt to return an indexed reader that supports non-linear traversal, else return the non-indexed reader */ public static ReferenceSequenceFile getReferenceSequenceFile(final File file, final boolean truncateNamesAtWhitespace, final boolean preferIndexed) { - return getReferenceSequenceFile(file.toPath(), truncateNamesAtWhitespace, preferIndexed); + return getReferenceSequenceFile(IOUtil.toPath(file), truncateNamesAtWhitespace, preferIndexed); } /** @@ -118,25 +130,83 @@ public static ReferenceSequenceFile getReferenceSequenceFile(final Path path, fi // this should thrown an exception if the fasta file is not supported getFastaExtension(path); // Using faidx requires truncateNamesAtWhitespace - if (truncateNamesAtWhitespace && preferIndexed && IndexedFastaSequenceFile.canCreateIndexedFastaReader(path)) { + if (truncateNamesAtWhitespace && preferIndexed && canCreateIndexedFastaReader(path)) { try { - return new IndexedFastaSequenceFile(path); - } - catch (final FileNotFoundException e) { - throw new IllegalStateException("Should never happen, because existence of files has been checked.", e); + return IOUtil.isBlockCompressed(path, true) ? new BlockCompressedIndexedFastaSequenceFile(path) : new IndexedFastaSequenceFile(path); + } catch (final IOException e) { + throw new SAMException("Error opening FASTA: " + path, e); } } else { return new FastaSequenceFile(path, truncateNamesAtWhitespace); } } + /** + * Checks if the provided FASTA file can be open as indexed. + * + *

For a FASTA file to be indexed, it requires to have: + *

+ * + * @param fastaFile the reference sequence file path. + * @return {@code true} if the file can be open as indexed; {@code false} otherwise. + */ + public static boolean canCreateIndexedFastaReader(final Path fastaFile) { + // this should thrown an exception if the fasta file is not supported + getFastaExtension(fastaFile); + + // both the FASTA file should exists and the .fai index should exist + if (Files.exists(fastaFile) && Files.exists(getFastaIndexFileName(fastaFile))) { + // open the file for checking for block-compressed input + try { + // if it is bgzip, it requires the .gzi index + return !IOUtil.isBlockCompressed(fastaFile, true) || + Files.exists(GZIIndex.resolveIndexNameForBgzipFile(fastaFile)); + } catch (IOException e) { + return false; + } + } + return false; + } + + /** + * Return an instance of ReferenceSequenceFile using the given fasta sequence file stream, optional index stream, + * and no sequence dictionary + * + * @param source The named source of the reference file (used in error messages). + * @param in The input stream to read the fasta file from. + * @param index The index, or null to return a non-indexed reader. + */ + public static ReferenceSequenceFile getReferenceSequenceFile(final String source, final SeekableStream in, final FastaSequenceIndex index) { + return getReferenceSequenceFile(source, in, index, null, true); + } + + /** + * Return an instance of ReferenceSequenceFile using the given fasta sequence file stream and optional index stream + * and sequence dictionary. + * + * @param source The named source of the reference file (used in error messages). + * @param in The input stream to read the fasta file from. + * @param index The index, or null to return a non-indexed reader. + * @param dictionary The sequence dictionary, or null if there isn't one. + * @param truncateNamesAtWhitespace if true, only include the first word of the sequence name + */ + public static ReferenceSequenceFile getReferenceSequenceFile(final String source, final SeekableStream in, final FastaSequenceIndex index, final SAMSequenceDictionary dictionary, final boolean truncateNamesAtWhitespace) { + if (truncateNamesAtWhitespace && index != null) { + return new IndexedFastaSequenceFile(source, in, index, dictionary); + } + return new FastaSequenceFile(source, in, dictionary, truncateNamesAtWhitespace); + } + /** * Returns the default dictionary name for a FASTA file. * * @param file the reference sequence file on disk. */ public static File getDefaultDictionaryForReferenceSequence(final File file) { - return getDefaultDictionaryForReferenceSequence(file.toPath()).toFile(); + return getDefaultDictionaryForReferenceSequence(IOUtil.toPath(file)).toFile(); } /** @@ -150,6 +220,22 @@ public static Path getDefaultDictionaryForReferenceSequence(final Path path) { return path.resolveSibling(name.substring(0, extensionIndex) + IOUtil.DICT_FILE_EXTENSION); } + /** + * Loads the sequence dictionary from a FASTA file input stream. + * + * @param in the FASTA file input stream. + * @return the sequence dictionary, or null if the header has no dictionary or it was empty. + */ + public static SAMSequenceDictionary loadDictionary(final InputStream in) { + final SAMTextHeaderCodec codec = new SAMTextHeaderCodec(); + final BufferedLineReader reader = new BufferedLineReader(in); + final SAMFileHeader header = codec.decode(reader, null); + if (header.getSequenceDictionary().isEmpty()) { + return null; + } + return header.getSequenceDictionary(); + } + /** * Returns the FASTA extension for the path. * diff --git a/src/main/java/htsjdk/samtools/reference/SamLocusAndReferenceIterator.java b/src/main/java/htsjdk/samtools/reference/SamLocusAndReferenceIterator.java new file mode 100644 index 0000000000..ec8d0e01b5 --- /dev/null +++ b/src/main/java/htsjdk/samtools/reference/SamLocusAndReferenceIterator.java @@ -0,0 +1,115 @@ +/* + * The MIT License + * + * Copyright (c) 2009-2018 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.reference; + +import htsjdk.samtools.util.IterableOnceIterator; +import htsjdk.samtools.util.SamLocusIterator; +import htsjdk.samtools.util.SequenceUtil; + +import java.util.List; + +import static htsjdk.samtools.util.SamLocusIterator.*; + +/** + * Iterator that traverses a SAM File and a ReferenceFile, accumulating information on a per-locus basis. + * Only loci that are covered by the input reads are returned. + * Duplicate reads and non-primary alignments are filtered out. + * Iterator element holds both pileup (in the form of a LocusInfo object) and the reference base + * + * @author Yossi Farjoun + */ +public class SamLocusAndReferenceIterator extends IterableOnceIterator { + + private final ReferenceSequenceFileWalker referenceSequenceFileWalker; + private final SamLocusIterator locusIterator; + + /** + * Constructor that takes a {@link ReferenceSequenceFile} and a {@link SamLocusIterator}. + * The inputs must have equal {@link htsjdk.samtools.SAMSequenceDictionary SAMSequenceDictionary}s and an {@link IllegalArgumentException} + * will be thrown otherwise. + * + * @param referenceFile + * @param locusIterator + * + * @throws IllegalArgumentException if arguments have non-equal {@link htsjdk.samtools.SAMSequenceDictionary SAMSequenceDictionary}s + */ + public SamLocusAndReferenceIterator(final ReferenceSequenceFileWalker referenceFile, final SamLocusIterator locusIterator) + throws IllegalArgumentException { + if(!SequenceUtil.areSequenceDictionariesEqual( + locusIterator.getHeader().getSequenceDictionary(), + referenceFile.getSequenceDictionary())) { + throw new IllegalArgumentException("reference and locus iterator have difference dictionaries." + + locusIterator.getHeader().getSequenceDictionary().toString() + + referenceFile.getSequenceDictionary().toString()); + } + this.referenceSequenceFileWalker = referenceFile; + this.locusIterator = locusIterator; + } + + @Override + public boolean hasNext() { + return locusIterator.hasNext(); + } + + @Override + public SAMLocusAndReference next() { + final LocusInfo locus = locusIterator.next(); + final ReferenceSequence referenceSequence = referenceSequenceFileWalker.get(locus.getSequenceIndex(), locus.getSequenceName(), + locus.getSequenceLength()); + + //position is 1-based...arrays are 0-based! + return new SAMLocusAndReference(locus, referenceSequence.getBases()[locus.getPosition() - 1]); + } + + /** Small class to hold together + * a {@link LocusInfo} and the reference base over that locus. + */ + public static class SAMLocusAndReference { + public LocusInfo getLocus() { + return locus; + } + + private final LocusInfo locus; + + public byte getReferenceBase() { + return referenceBase; + } + + private final byte referenceBase; + + public SAMLocusAndReference(final LocusInfo locus, final byte referenceBase) { + this.locus = locus; + this.referenceBase = referenceBase; + } + + /** + * Getter + * @return The {@link RecordAndOffset} that overlap this locus. Extracted + * from the {@link LocusInfo}. + */ + public List getRecordAndOffsets() { + return locus.getRecordAndOffsets(); + } + } +} diff --git a/src/main/java/htsjdk/samtools/seekablestream/ReadableSeekableStreamByteChannel.java b/src/main/java/htsjdk/samtools/seekablestream/ReadableSeekableStreamByteChannel.java new file mode 100644 index 0000000000..054de42a51 --- /dev/null +++ b/src/main/java/htsjdk/samtools/seekablestream/ReadableSeekableStreamByteChannel.java @@ -0,0 +1,70 @@ +package htsjdk.samtools.seekablestream; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.NonWritableChannelException; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SeekableByteChannel; + +/** + * A class to wrap a {@link SeekableStream} in a read-only {@link SeekableByteChannel}. + */ +public class ReadableSeekableStreamByteChannel implements SeekableByteChannel { + + private final SeekableStream seekableStream; + private final ReadableByteChannel rbc; + private long pos; + + public ReadableSeekableStreamByteChannel(SeekableStream seekableStream) { + this.seekableStream = seekableStream; + this.rbc = Channels.newChannel(seekableStream); + } + + @Override + public int read(ByteBuffer dst) throws IOException { + int n = rbc.read(dst); + if (n > 0) { + pos += n; + } + return n; + } + + @Override + public int write(ByteBuffer src) throws IOException { + throw new NonWritableChannelException(); + } + + @Override + public long position() { + return pos; + } + + @Override + public SeekableByteChannel position(long newPosition) throws IOException { + // ReadableByteChannel is not buffered, so it reads through + seekableStream.seek(newPosition); + pos = newPosition; + return this; + } + + @Override + public long size() { + return seekableStream.length(); + } + + @Override + public SeekableByteChannel truncate(long size) { + throw new NonWritableChannelException(); + } + + @Override + public boolean isOpen() { + return rbc.isOpen(); + } + + @Override + public void close() throws IOException { + rbc.close(); + } +} diff --git a/src/main/java/htsjdk/samtools/seekablestream/SeekableBufferedStream.java b/src/main/java/htsjdk/samtools/seekablestream/SeekableBufferedStream.java index 0c89b0166d..8a1f1d5521 100644 --- a/src/main/java/htsjdk/samtools/seekablestream/SeekableBufferedStream.java +++ b/src/main/java/htsjdk/samtools/seekablestream/SeekableBufferedStream.java @@ -43,8 +43,22 @@ private ExtBufferedInputStream(final InputStream inputStream, final int i) { /** Returns the number of bytes that can be read from the buffer without reading more into the buffer. */ int getBytesInBufferAvailable() { - if (this.count == this.pos) return 0; // documented test for "is buffer empty" - else return this.buf.length - this.pos; + return this.count - this.pos; + } + + /** Return true if the position can be changed by the given delta and remain in the buffer. */ + boolean canChangePos(long delta) { + long newPos = this.pos + delta; + return newPos >= 0 && newPos < this.count; + } + + /** Changes the position in the buffer by a given delta. */ + void changePos(int delta) { + int newPos = this.pos + delta; + if (newPos < 0 || newPos >= this.count) { + throw new IllegalArgumentException("New position not in buffer pos=" + this.pos + ", delta=" + delta); + } + this.pos = newPos; } } @@ -80,16 +94,31 @@ public long skip(final long skipLength) throws IOException { return retval; } else { final long position = this.position + skipLength; - seek(position); + seekInternal(position); return skipLength; } } @Override public void seek(final long position) throws IOException { - this.position = position; + if (this.position == position) { + return; + } + // check if the seek is within the buffer + long delta = position - this.position; + if (this.bufferedStream.canChangePos(delta)) { + // casting to an int is safe since the buffer is less than the size of an int + this.bufferedStream.changePos((int) delta); + this.position = position; + } else { + seekInternal(position); + } + } + + private void seekInternal(final long position) throws IOException { wrappedStream.seek(position); bufferedStream = new ExtBufferedInputStream(wrappedStream, bufferSize); + this.position = position; } @Override diff --git a/src/main/java/htsjdk/samtools/seekablestream/SeekableHTTPStream.java b/src/main/java/htsjdk/samtools/seekablestream/SeekableHTTPStream.java index 640a14d989..a846fe4512 100644 --- a/src/main/java/htsjdk/samtools/seekablestream/SeekableHTTPStream.java +++ b/src/main/java/htsjdk/samtools/seekablestream/SeekableHTTPStream.java @@ -100,9 +100,12 @@ public int read(byte[] buffer, int offset, int len) throws IOException { if (offset < 0 || len < 0 || (offset + len) > buffer.length) { throw new IndexOutOfBoundsException("Offset="+offset+",len="+len+",buflen="+buffer.length); } - if (len == 0 || position == contentLength) { + if (len == 0 ) { return 0; } + if (position == contentLength) { + return -1; + } HttpURLConnection connection = null; InputStream is = null; diff --git a/src/main/java/htsjdk/samtools/seekablestream/SeekableStream.java b/src/main/java/htsjdk/samtools/seekablestream/SeekableStream.java index 99a53f68df..9d2a82093c 100644 --- a/src/main/java/htsjdk/samtools/seekablestream/SeekableStream.java +++ b/src/main/java/htsjdk/samtools/seekablestream/SeekableStream.java @@ -89,6 +89,28 @@ public void readFully(byte b[]) throws IOException { } } + /** + * The return value of this method is unusable for any purpose, and we are only implementing it + * because certain Java classes like {@link java.util.zip.GZIPInputStream} incorrectly rely on + * it to detect EOF + * + *

If {@code eof() == true}, 0 bytes are available. Otherwise, available bytes are the + * difference between the length of the stream ({@link #length()}) and the current position + * ({@link #position()}. + * + * @return {@code 0} if the end of the file has been reached or the length cannot be determined; + * number of bytes remaining in the stream otherwise. + */ + @Override + public int available() throws IOException { + if (eof()) { + return 0; + } + final long remaining = length() - position(); + // the remaining might be negative if the length is not available (0) + return (remaining < 0) ? 0 : (int) remaining; + } + /** * Mark the current position of the stream. * diff --git a/src/main/java/htsjdk/samtools/util/AbstractLocusInfo.java b/src/main/java/htsjdk/samtools/util/AbstractLocusInfo.java index d699dce8f5..95150e0c51 100644 --- a/src/main/java/htsjdk/samtools/util/AbstractLocusInfo.java +++ b/src/main/java/htsjdk/samtools/util/AbstractLocusInfo.java @@ -40,7 +40,7 @@ * @author Darina_Nikolaeva@epam.com, EPAM Systems, Inc. * */ -public class AbstractLocusInfo implements Locus { +public class AbstractLocusInfo implements Locus, Locatable { /** * Reference sequence, to which the reads are aligned. **/ @@ -145,4 +145,19 @@ public int size() { public boolean isEmpty() { return getRecordAndOffsets().isEmpty(); } + + @Override + public String getContig() { + return getSequenceName(); + } + + @Override + public int getStart() { + return getPosition(); + } + + @Override + public int getEnd() { + return getPosition(); + } } diff --git a/src/main/java/htsjdk/samtools/util/AbstractLocusIterator.java b/src/main/java/htsjdk/samtools/util/AbstractLocusIterator.java index bbfb416f8c..9f5134f627 100644 --- a/src/main/java/htsjdk/samtools/util/AbstractLocusIterator.java +++ b/src/main/java/htsjdk/samtools/util/AbstractLocusIterator.java @@ -147,6 +147,13 @@ public abstract class AbstractLocusIterator BLOCK_COMPRESSED_EXTENSIONS = Collections.unmodifiableSet(new HashSet(Arrays.asList(".gz", ".gzip", ".bgz", ".bgzf"))); + private static int compressionLevel = Defaults.COMPRESSION_LEVEL; /** @@ -353,34 +358,12 @@ public static Path getDefaultTmpDirPath() { } /** - * Deletes on exit a path by creating a shutdown hook. - */ - public static void deleteOnExit(final Path path) { - // add a shutdown hook to remove the path on exit - Runtime.getRuntime().addShutdownHook(new DeletePathThread(path)); - } - - /** - * WARNING: visible for testing. Do not use. - * - * Class for delete a path, used in a shutdown hook for delete on exit. + * Register a {@link Path} for deletion on JVM exit. * - * @see #deleteOnExit(Path) + * @see DeleteOnExitPathHook */ - static final class DeletePathThread extends Thread { - - private final Path path; - - DeletePathThread(Path path) {this.path = path;} - - @Override - public void run() { - try { - Files.deleteIfExists(path); - } catch (IOException e) { - throw new RuntimeIOException(e); - } - } + public static void deleteOnExit(final Path path) { + DeleteOnExitPathHook.add(path); } /** Returns the name of the file minus the extension (i.e. text after the last "." in the filename). */ @@ -431,7 +414,7 @@ public static boolean isUrl(final String input) { * @param file the file to check for readability */ public static void assertFileIsReadable(final File file) { - assertFileIsReadable(file == null ? null : file.toPath()); + assertFileIsReadable(toPath(file)); } /** @@ -538,7 +521,7 @@ public static void assertFilesAreWritable(final List files) { * @param dir the dir to check for writability */ public static void assertDirectoryIsWritable(final File dir) { - final Path asPath = (dir == null) ? null : dir.toPath(); + final Path asPath = IOUtil.toPath(dir); assertDirectoryIsWritable(asPath); } @@ -630,7 +613,7 @@ public static void assertFileSizeNonZero(final File file) { * @return the input stream to read from */ public static InputStream openFileForReading(final File file) { - return openFileForReading(file.toPath()); + return openFileForReading(toPath(file)); } /** @@ -663,7 +646,7 @@ public static InputStream openFileForReading(final Path path) { * @return the input stream to read from */ public static InputStream openGzipFileForReading(final File file) { - return openGzipFileForReading(file.toPath()); + return openGzipFileForReading(toPath(file)); } /** @@ -903,7 +886,7 @@ public static File createTempDir(final String prefix, final String suffix) { /** Checks that a file exists and is readable, and then returns a buffered reader for it. */ public static BufferedReader openFileForBufferedReading(final File file) { - return openFileForBufferedReading(file.toPath()); + return openFileForBufferedReading(toPath(file)); } /** Checks that a path exists and is readable, and then returns a buffered reader for it. */ @@ -1154,6 +1137,16 @@ public static List getPaths(List uriStrings) throws RuntimeIOExcep }).collect(Collectors.toList()); } + /* + * Converts the File to a Path, preserving nullness. + * + * @param fileOrNull a File, or null + * @return the corresponding Path (or null) + */ + public static Path toPath(File fileOrNull) { + return (null == fileOrNull ? null : fileOrNull.toPath()); + } + /** Takes a list of Files and converts them to a list of Paths * Runs .toPath() on the contents of the input. * @@ -1174,4 +1167,105 @@ public static List filesToPaths(Collection files){ public static Path addExtension(Path path, String extension) { return path.resolveSibling(path.getFileName() + extension); } + + /** + * Checks if the provided path is block-compressed. + * + *

Note that using {@code checkExtension=true} would avoid the cost of opening the file, but + * if {@link #hasBlockCompressedExtension(String)} returns {@code false} this would not detect + * block-compressed files such BAM. + * + * @param path file to check if it is block-compressed. + * @param checkExtension if {@code true}, checks the extension before opening the file. + * @return {@code true} if the file is block-compressed; {@code false} otherwise. + * @throws IOException if there is an I/O error. + */ + public static boolean isBlockCompressed(final Path path, final boolean checkExtension) throws IOException { + if (checkExtension && !hasBlockCompressedExtension(path)) { + return false; + } + try (final InputStream stream = new BufferedInputStream(Files.newInputStream(path), Math.max(Defaults.BUFFER_SIZE, BlockCompressedStreamConstants.MAX_COMPRESSED_BLOCK_SIZE))) { + return BlockCompressedInputStream.isValidFile(stream); + } + } + + /** + * Checks if the provided path is block-compressed (including extension). + * + *

Note that block-compressed file extensions {@link #BLOCK_COMPRESSED_EXTENSIONS} are not + * checked by this method. + * + * @param path file to check if it is block-compressed. + * @return {@code true} if the file is block-compressed; {@code false} otherwise. + * @throws IOException if there is an I/O error. + */ + public static boolean isBlockCompressed(final Path path) throws IOException { + return isBlockCompressed(path, false); + } + + /** + * Checks if a file ends in one of the {@link #BLOCK_COMPRESSED_EXTENSIONS}. + * + * @param fileName string name for the file. May be an HTTP/S url. + * + * @return {@code true} if the file has a block-compressed extension; {@code false} otherwise. + */ + public static boolean hasBlockCompressedExtension (final String fileName) { + String cleanedPath = stripQueryStringIfPathIsAnHttpUrl(fileName); + for (final String extension : BLOCK_COMPRESSED_EXTENSIONS) { + if (cleanedPath.toLowerCase().endsWith(extension)) + return true; + } + return false; + } + + /** + * Checks if a path ends in one of the {@link #BLOCK_COMPRESSED_EXTENSIONS}. + * + * @param path object to extract the name from. + * + * @return {@code true} if the path has a block-compressed extension; {@code false} otherwise. + */ + public static boolean hasBlockCompressedExtension(final Path path) { + return hasBlockCompressedExtension(path.getFileName().toString()); + } + + /** + * Checks if a file ends in one of the {@link #BLOCK_COMPRESSED_EXTENSIONS}. + * + * @param file object to extract the name from. + * + * @return {@code true} if the file has a block-compressed extension; {@code false} otherwise. + */ + public static boolean hasBlockCompressedExtension (final File file) { + return hasBlockCompressedExtension(file.getName()); + } + + /** + * Checks if a file ends in one of the {@link #BLOCK_COMPRESSED_EXTENSIONS}. + * + * @param uri file as an URI. + * + * @return {@code true} if the file has a block-compressed extension; {@code false} otherwise. + */ + public static boolean hasBlockCompressedExtension (final URI uri) { + String path = uri.getPath(); + return hasBlockCompressedExtension(path); + } + + /** + * Remove http query before checking extension + * Path might be a local file, in which case a '?' is a legal part of the filename. + * @param path a string representing some sort of path, potentially an http url + * @return path with no trailing queryString (ex: http://something.com/path.vcf?stuff=something => http://something.com/path.vcf) + */ + private static String stripQueryStringIfPathIsAnHttpUrl(String path) { + if(path.startsWith("http://") || path.startsWith("https://")) { + int qIdx = path.indexOf('?'); + if (qIdx > 0) { + return path.substring(0, qIdx); + } + } + return path; + } } diff --git a/src/main/java/htsjdk/samtools/util/Interval.java b/src/main/java/htsjdk/samtools/util/Interval.java index 51e91270af..8eabcbc432 100644 --- a/src/main/java/htsjdk/samtools/util/Interval.java +++ b/src/main/java/htsjdk/samtools/util/Interval.java @@ -44,23 +44,29 @@ public class Interval implements Comparable, Cloneable, Locatable { * position is less than the start position an exception is thrown. * * @param sequence the name of the sequence - * @param start the start position of the interval on the sequence - * @param end the end position of the interval on the sequence + * @param start the start position of the interval on the sequence + * @param end the end position of the interval on the sequence */ public Interval(final String sequence, final int start, final int end) { this(sequence, start, end, false, null); } + /** + * Constructs an interval with the supplied {@link Locatable}. + */ + public Interval(final Locatable locatable) { + this(locatable.getContig(), locatable.getStart(), locatable.getEnd()); + } + /** * Constructs an interval with the supplied sequence and start, end, strand and name. * If the end position is less than the start position an exception is thrown. * * @param sequence the name of the sequence - * @param start the start position of the interval on the sequence - * @param end the end position of the interval on the sequence + * @param start the start position of the interval on the sequence + * @param end the end position of the interval on the sequence * @param negative true to indicate negative strand, false otherwise - * @param name the name (possibly null) of the interval - * + * @param name the name (possibly null) of the interval */ public Interval(final String sequence, final int start, final int end, final boolean negative, final String name) { this.contig = sequence; @@ -70,63 +76,90 @@ public Interval(final String sequence, final int start, final int end, final boo this.name = name; } - /** Gets the name of the sequence on which the interval resides. + /** + * Gets the name of the sequence on which the interval resides. * This is a simple alias of getContig() + * * @deprecated use getContig() instead */ @Deprecated - public String getSequence() { return getContig(); } - + public String getSequence() { + return getContig(); + } - /** Returns true if the interval is on the negative strand, otherwise false. */ - public boolean isNegativeStrand() { return this.negativeStrand; } + /** + * Returns true if the interval is on the negative strand, otherwise false. + */ + public boolean isNegativeStrand() { + return this.negativeStrand; + } - /** Returns true if the interval is on the positive strand, otherwise false. */ - public boolean isPositiveStrand() { return !this.negativeStrand; } + /** + * Returns true if the interval is on the positive strand, otherwise false. + */ + public boolean isPositiveStrand() { + return !this.negativeStrand; + } - /** Returns the name of the interval, possibly null. */ - public String getName() { return this.name; } + /** + * Returns the name of the interval, possibly null. + */ + public String getName() { + return this.name; + } - /** Returns true if this interval overlaps the other interval, otherwise false. */ + /** + * Returns true if this interval overlaps the other interval, otherwise false. + */ public boolean intersects(final Interval other) { - return (this.getContig().equals(other.getContig()) && - CoordMath.overlaps(this.getStart(), this.getEnd(), other.getStart(), other.getEnd())); + return (this.getContig().equals(other.getContig()) && + CoordMath.overlaps(this.getStart(), this.getEnd(), other.getStart(), other.getEnd())); } public int getIntersectionLength(final Interval other) { if (this.intersects(other)) { - return (int)CoordMath.getOverlap(this.getStart(), this.getEnd(), other.getStart(), other.getEnd()); + return (int) CoordMath.getOverlap(this.getStart(), this.getEnd(), other.getStart(), other.getEnd()); } return 0; } - - /** Returns a new Interval that represents the intersection between the two intervals. */ + /** + * Returns a new Interval that represents the intersection between the two intervals. + */ public Interval intersect(final Interval that) { if (!intersects(that)) throw new IllegalArgumentException(that + " does not intersect " + this); return new Interval(this.getContig(), - Math.max(this.getStart(), that.getStart()), - Math.min(this.getEnd(), that.getEnd()), - this.negativeStrand, - this.name + " intersection " + that.name); + Math.max(this.getStart(), that.getStart()), + Math.min(this.getEnd(), that.getEnd()), + this.negativeStrand, + this.name + " intersection " + that.name); } - - /** Returns true if this interval overlaps the other interval, otherwise false. */ + /** + * Returns true if this interval overlaps the other interval, otherwise false. + */ public boolean abuts(final Interval other) { return this.getContig().equals(other.getContig()) && - (this.getStart() == other.getEnd() + 1 || other.getStart() == this.getEnd() + 1); + (this.getStart() == other.getEnd() + 1 || other.getStart() == this.getEnd() + 1); } - /** Gets the length of this interval. */ - public int length() { return this.getEnd() - this.getStart() + 1; } + /** + * Gets the length of this interval. + */ + public int length() { + return this.getEnd() - this.getStart() + 1; + } - /** Returns a new interval that is padded by the amount of bases specified on either side. */ + /** + * Returns a new interval that is padded by the amount of bases specified on either side. + */ public Interval pad(final int left, final int right) { - return new Interval(this.getContig(), this.getStart()-left, this.getEnd()+right, this.negativeStrand, this.name); + return new Interval(this.getContig(), this.getStart() - left, this.getEnd() + right, this.negativeStrand, this.name); } - /** Counts the total number of bases a collection of intervals. */ + /** + * Counts the total number of bases a collection of intervals. + */ public static long countBases(final Collection intervals) { long total = 0; for (final Interval i : intervals) { @@ -136,7 +169,6 @@ public static long countBases(final Collection intervals) { return total; } - /** * Sort based on sequence.compareTo, then start pos, then end pos * with null objects coming lexically last @@ -149,8 +181,7 @@ public int compareTo(final Interval that) { if (result == 0) { if (this.getStart() == that.getStart()) { result = this.getEnd() - that.getEnd(); - } - else { + } else { result = this.getStart() - that.getStart(); } } @@ -158,12 +189,14 @@ public int compareTo(final Interval that) { return result; } - /** Equals method that agrees with {@link #compareTo(Interval)}. */ + /** + * Equals method that agrees with {@link #compareTo(Interval)}. + */ public boolean equals(final Object other) { if (!(other instanceof Interval)) return false; else if (this == other) return true; else { - Interval that = (Interval)other; + Interval that = (Interval) other; return (this.compareTo(that) == 0); } } @@ -182,8 +215,11 @@ public String toString() { @Override public Interval clone() { - try { return (Interval) super.clone(); } - catch (CloneNotSupportedException cnse) { throw new SAMException("That's unpossible", cnse); } + try { + return (Interval) super.clone(); + } catch (CloneNotSupportedException cnse) { + throw new SAMException("That's unpossible", cnse); + } } @Override diff --git a/src/main/java/htsjdk/samtools/util/IntervalList.java b/src/main/java/htsjdk/samtools/util/IntervalList.java index a5d2a8e000..6691fa5745 100644 --- a/src/main/java/htsjdk/samtools/util/IntervalList.java +++ b/src/main/java/htsjdk/samtools/util/IntervalList.java @@ -396,7 +396,7 @@ public static IntervalList copyOf(final IntervalList list){ * @return an IntervalList object that contains the headers and intervals from the file */ public static IntervalList fromFile(final File file) { - return fromPath(file.toPath()); + return fromPath(IOUtil.toPath(file)); } /** diff --git a/src/main/java/htsjdk/samtools/util/Md5CalculatingOutputStream.java b/src/main/java/htsjdk/samtools/util/Md5CalculatingOutputStream.java index 8b4c643a37..c002b5bf01 100755 --- a/src/main/java/htsjdk/samtools/util/Md5CalculatingOutputStream.java +++ b/src/main/java/htsjdk/samtools/util/Md5CalculatingOutputStream.java @@ -27,7 +27,6 @@ import java.io.BufferedWriter; import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; @@ -68,7 +67,7 @@ public Md5CalculatingOutputStream(OutputStream os, Path digestFile) { } public Md5CalculatingOutputStream(OutputStream os, File digestFile) { - this(os, digestFile == null ? (Path) null : digestFile.toPath()); + this(os, IOUtil.toPath(digestFile)); } @Override diff --git a/src/main/java/htsjdk/samtools/util/ProgressLoggerInterface.java b/src/main/java/htsjdk/samtools/util/ProgressLoggerInterface.java index a3ef7bcf8c..becc802813 100644 --- a/src/main/java/htsjdk/samtools/util/ProgressLoggerInterface.java +++ b/src/main/java/htsjdk/samtools/util/ProgressLoggerInterface.java @@ -34,5 +34,5 @@ public interface ProgressLoggerInterface { boolean record(final String chrom, final int pos); boolean record(final SAMRecord rec); boolean record(final SAMRecord... recs); - + default void reset() {}; } diff --git a/src/main/java/htsjdk/samtools/util/SamLocusIterator.java b/src/main/java/htsjdk/samtools/util/SamLocusIterator.java index dc6745f5d6..daf8dae032 100644 --- a/src/main/java/htsjdk/samtools/util/SamLocusIterator.java +++ b/src/main/java/htsjdk/samtools/util/SamLocusIterator.java @@ -23,12 +23,7 @@ */ package htsjdk.samtools.util; -import htsjdk.samtools.AlignmentBlock; -import htsjdk.samtools.CigarElement; -import htsjdk.samtools.CigarOperator; -import htsjdk.samtools.SAMRecord; -import htsjdk.samtools.SAMSequenceRecord; -import htsjdk.samtools.SamReader; +import htsjdk.samtools.*; import java.util.ArrayList; import java.util.Collections; @@ -137,7 +132,6 @@ void accumulateIndels(SAMRecord rec) { final CigarElement e = cigar.get(elementIndex); final CigarOperator operator = e.getOperator(); if (operator.equals(CigarOperator.I)) { - System.err.println(""); // insertions are included in the previous base accumulator.get(refBase - 1).addInserted(rec, readBase); readBase += e.getLength(); diff --git a/src/main/java/htsjdk/samtools/util/SortingCollection.java b/src/main/java/htsjdk/samtools/util/SortingCollection.java index 46b84c117b..cec8a74c93 100644 --- a/src/main/java/htsjdk/samtools/util/SortingCollection.java +++ b/src/main/java/htsjdk/samtools/util/SortingCollection.java @@ -26,7 +26,6 @@ import htsjdk.samtools.Defaults; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -50,14 +49,15 @@ * to a temporary directory if there are more records added than will fit in memory. As a result of this, * the objects returned may not be identical to the objects added to the collection, but they should be * equal as determined by the codec used to write them to disk and read them back. - * + *

* When iterating over the collection, the number of file handles required is numRecordsInCollection/maxRecordsInRam. * If this becomes a limiting factor, a file handle cache could be added. - * + *

* If Snappy DLL is available and snappy.disable system property is not set to true, then Snappy is used * to compress temporary files. */ public class SortingCollection implements Iterable { + private static final Log log = Log.getInstance(SortingCollection.class); /** * Client must implement this class, which defines the way in which records are written to and @@ -66,23 +66,24 @@ public class SortingCollection implements Iterable { public interface Codec extends Cloneable { /** * Where to write encoded output - * @param os */ void setOutputStream(OutputStream os); /** * Where to read encoded input from - * @param is */ void setInputStream(InputStream is); + /** * Write object to output stream + * * @param val what to write */ void encode(T val); /** * Read the next record from the input stream and convert into a java object. + * * @return null if no more records. Should throw exception if EOF is encountered in the middle of * a record. */ @@ -96,12 +97,11 @@ public interface Codec extends Cloneable { Codec clone(); } - /** Directories where files of sorted records go. */ + /** + * Directories where files of sorted records go. + */ private final Path[] tmpDirs; - /** The minimum amount of space free on a temp filesystem to write a file there. */ - private final long TMP_SPACE_FREE = IOUtil.FIVE_GBS; - /** * Used to write records to file, and used as a prototype to create codecs for reading. */ @@ -129,18 +129,23 @@ public interface Codec extends Cloneable { private boolean destructiveIteration = true; - private TempStreamFactory tempStreamFactory = new TempStreamFactory(); + private final TempStreamFactory tempStreamFactory = new TempStreamFactory(); + + private final boolean printRecordSizeSampling; /** * Prepare to accumulate records to be sorted - * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. - * @param codec For writing records to file and reading them back into RAM - * @param comparator Defines output sort order + * + * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. + * @param codec For writing records to file and reading them back into RAM + * @param comparator Defines output sort order * @param maxRecordsInRam how many records to accumulate before spilling to disk - * @param tmpDir Where to write files of records that will not fit in RAM + * @param printRecordSizeSampling If true record size will be sampled and output at DEBUG log level + * @param tmpDir Where to write files of records that will not fit in RAM */ private SortingCollection(final Class componentType, final SortingCollection.Codec codec, - final Comparator comparator, final int maxRecordsInRam, final Path... tmpDir) { + final Comparator comparator, final int maxRecordsInRam, + final boolean printRecordSizeSampling, final Path... tmpDir) { if (maxRecordsInRam <= 0) { throw new IllegalArgumentException("maxRecordsInRam must be > 0"); } @@ -153,7 +158,10 @@ private SortingCollection(final Class componentType, final SortingCollection. this.codec = codec; this.comparator = comparator; this.maxRecordsInRam = maxRecordsInRam; - this.ramRecords = (T[])Array.newInstance(componentType, maxRecordsInRam); + @SuppressWarnings("unchecked") + T[] ramRecords = (T[]) Array.newInstance(componentType, maxRecordsInRam); + this.ramRecords = ramRecords; + this.printRecordSizeSampling = printRecordSizeSampling; } public void add(final T rec) { @@ -164,7 +172,27 @@ public void add(final T rec) { throw new IllegalStateException("Cannot add after calling iterator()"); } if (numRecordsInRam == maxRecordsInRam) { + + long startMem = 0; + if (printRecordSizeSampling) { + // Garbage collect and get free memory + Runtime.getRuntime().gc(); + startMem = Runtime.getRuntime().freeMemory(); + } + spillToDisk(); + + if (printRecordSizeSampling) { + //Garbage collect again and get free memory + Runtime.getRuntime().gc(); + long endMem = Runtime.getRuntime().freeMemory(); + + long usedBytes = endMem - startMem; + log.debug(String.format("%d records in ram required approximately %s memory or %s per record. ", maxRecordsInRam, + StringUtil.humanReadableByteCount(usedBytes), + StringUtil.humanReadableByteCount(usedBytes / maxRecordsInRam))); + + } } ramRecords[numRecordsInRam++] = rec; } @@ -217,43 +245,38 @@ public void setDestructiveIteration(boolean destructiveIteration) { */ public void spillToDisk() { try { - Arrays.sort(this.ramRecords, 0, this.numRecordsInRam, this.comparator); + Arrays.parallelSort(this.ramRecords, 0, this.numRecordsInRam, this.comparator); + final Path f = newTempFile(); - OutputStream os = null; - try { - os = tempStreamFactory.wrapTempOutputStream(Files.newOutputStream(f), Defaults.BUFFER_SIZE); + try (OutputStream os + = tempStreamFactory.wrapTempOutputStream(Files.newOutputStream(f), Defaults.BUFFER_SIZE)) { this.codec.setOutputStream(os); for (int i = 0; i < this.numRecordsInRam; ++i) { this.codec.encode(ramRecords[i]); // Facilitate GC this.ramRecords[i] = null; } - os.flush(); } catch (RuntimeIOException ex) { throw new RuntimeIOException("Problem writing temporary file " + f.toUri() + ". Try setting TMP_DIR to a file system with lots of space.", ex); - } finally { - if (os != null) { - os.close(); - } } this.numRecordsInRam = 0; this.files.add(f); - - } - catch (IOException e) { + } catch (IOException e) { throw new RuntimeIOException(e); } } + /** * Creates a new tmp file on one of the available temp filesystems, registers it for deletion * on JVM exit and then returns it. */ private Path newTempFile() throws IOException { - return IOUtil.newTempPath("sortingcollection.", ".tmp", this.tmpDirs, TMP_SPACE_FREE); + /* The minimum amount of space free on a temp filesystem to write a file there. */ + return IOUtil.newTempPath("sortingcollection.", ".tmp", this.tmpDirs, IOUtil.FIVE_GBS); } /** @@ -288,12 +311,11 @@ public void cleanup() { /** * Syntactic sugar around the ctor, to save some typing of type parameters * - * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. - * @param codec For writing records to file and reading them back into RAM - * @param comparator Defines output sort order + * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. + * @param codec For writing records to file and reading them back into RAM + * @param comparator Defines output sort order * @param maxRecordsInRAM how many records to accumulate in memory before spilling to disk - * @param tmpDir Where to write files of records that will not fit in RAM - * + * @param tmpDir Where to write files of records that will not fit in RAM * @deprecated since 2017-09. Use {@link #newInstance(Class, Codec, Comparator, int, Path...)} instead */ @Deprecated @@ -302,19 +324,18 @@ public static SortingCollection newInstance(final Class componentType, final Comparator comparator, final int maxRecordsInRAM, final File... tmpDir) { - return new SortingCollection(componentType, codec, comparator, maxRecordsInRAM, Arrays.stream(tmpDir).map(File::toPath).toArray(Path[]::new)); + return new SortingCollection<>(componentType, codec, comparator, maxRecordsInRAM, false, Arrays.stream(tmpDir).map(File::toPath).toArray(Path[]::new)); } /** * Syntactic sugar around the ctor, to save some typing of type parameters * - * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. - * @param codec For writing records to file and reading them back into RAM - * @param comparator Defines output sort order + * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. + * @param codec For writing records to file and reading them back into RAM + * @param comparator Defines output sort order * @param maxRecordsInRAM how many records to accumulate in memory before spilling to disk - * @param tmpDirs Where to write files of records that will not fit in RAM - * + * @param tmpDirs Where to write files of records that will not fit in RAM * @deprecated since 2017-09. Use {@link #newInstanceFromPaths(Class, Codec, Comparator, int, Collection)} instead */ @Deprecated @@ -323,70 +344,105 @@ public static SortingCollection newInstance(final Class componentType, final Comparator comparator, final int maxRecordsInRAM, final Collection tmpDirs) { - return new SortingCollection(componentType, - codec, - comparator, - maxRecordsInRAM, - tmpDirs.stream().map(File::toPath).toArray(Path[]::new)); + return new SortingCollection<>(componentType, + codec, + comparator, + maxRecordsInRAM, + false, + tmpDirs.stream().map(File::toPath).toArray(Path[]::new)); } + /** + * Syntactic sugar around the ctor, to save some typing of type parameters. Writes files to java.io.tmpdir + * + * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. + * @param codec For writing records to file and reading them back into RAM + * @param comparator Defines output sort order + * @param maxRecordsInRAM how many records to accumulate in memory before spilling to disk + * @param printRecordSizeSampling If true record size will be sampled and output at DEBUG log level + */ + public static SortingCollection newInstance(final Class componentType, + final SortingCollection.Codec codec, + final Comparator comparator, + final int maxRecordsInRAM, + final boolean printRecordSizeSampling) { + final Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir")); + return new SortingCollection<>(componentType, codec, comparator, maxRecordsInRAM, printRecordSizeSampling, tmpDir); + } + + /** + * Syntactic sugar around the ctor, to save some typing of type parameters + * + * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. + * @param codec For writing records to file and reading them back into RAM + * @param comparator Defines output sort order + * @param maxRecordsInRAM how many records to accumulate in memory before spilling to disk + * @param printRecordSizeSampling If true record size will be sampled and output at DEBUG log level + * @param tmpDir Where to write files of records that will not fit in RAM + */ + public static SortingCollection newInstance(final Class componentType, + final SortingCollection.Codec codec, + final Comparator comparator, + final int maxRecordsInRAM, + final boolean printRecordSizeSampling, + final Path... tmpDir) { + return new SortingCollection<>(componentType, codec, comparator, maxRecordsInRAM, printRecordSizeSampling, tmpDir); + } /** * Syntactic sugar around the ctor, to save some typing of type parameters. Writes files to java.io.tmpdir * - * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. - * @param codec For writing records to file and reading them back into RAM - * @param comparator Defines output sort order + * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. + * @param codec For writing records to file and reading them back into RAM + * @param comparator Defines output sort order * @param maxRecordsInRAM how many records to accumulate in memory before spilling to disk */ public static SortingCollection newInstance(final Class componentType, final SortingCollection.Codec codec, final Comparator comparator, final int maxRecordsInRAM) { - final Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir")); - return new SortingCollection(componentType, codec, comparator, maxRecordsInRAM, tmpDir); + return new SortingCollection<>(componentType, codec, comparator, maxRecordsInRAM, false, tmpDir); } /** * Syntactic sugar around the ctor, to save some typing of type parameters * - * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. - * @param codec For writing records to file and reading them back into RAM - * @param comparator Defines output sort order + * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. + * @param codec For writing records to file and reading them back into RAM + * @param comparator Defines output sort order * @param maxRecordsInRAM how many records to accumulate in memory before spilling to disk - * @param tmpDir Where to write files of records that will not fit in RAM + * @param tmpDir Where to write files of records that will not fit in RAM */ public static SortingCollection newInstance(final Class componentType, - final SortingCollection.Codec codec, - final Comparator comparator, - final int maxRecordsInRAM, - final Path... tmpDir) { - return new SortingCollection(componentType, codec, comparator, maxRecordsInRAM, tmpDir); - + final SortingCollection.Codec codec, + final Comparator comparator, + final int maxRecordsInRAM, + final Path... tmpDir) { + return new SortingCollection<>(componentType, codec, comparator, maxRecordsInRAM, false, tmpDir); } /** * Syntactic sugar around the ctor, to save some typing of type parameters * - * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. - * @param codec For writing records to file and reading them back into RAM - * @param comparator Defines output sort order + * @param componentType Class of the record to be sorted. Necessary because of Java generic lameness. + * @param codec For writing records to file and reading them back into RAM + * @param comparator Defines output sort order * @param maxRecordsInRAM how many records to accumulate in memory before spilling to disk - * @param tmpDirs Where to write files of records that will not fit in RAM + * @param tmpDirs Where to write files of records that will not fit in RAM */ public static SortingCollection newInstanceFromPaths(final Class componentType, - final SortingCollection.Codec codec, - final Comparator comparator, - final int maxRecordsInRAM, - final Collection tmpDirs) { - return new SortingCollection(componentType, + final SortingCollection.Codec codec, + final Comparator comparator, + final int maxRecordsInRAM, + final Collection tmpDirs) { + return new SortingCollection<>(componentType, codec, comparator, maxRecordsInRAM, + false, tmpDirs.toArray(new Path[tmpDirs.size()])); - } /** @@ -396,10 +452,10 @@ class InMemoryIterator implements CloseableIterator { private int iterationIndex = 0; InMemoryIterator() { - Arrays.sort(SortingCollection.this.ramRecords, - 0, - SortingCollection.this.numRecordsInRam, - SortingCollection.this.comparator); + Arrays.parallelSort(SortingCollection.this.ramRecords, + 0, + SortingCollection.this.numRecordsInRam, + SortingCollection.this.comparator); } @Override @@ -434,7 +490,7 @@ public void remove() { * Each file is has records in sort order within the file. * This iterator automatically closes when it iterates to the end, but if not iterating * to the end it is a good idea to call close(). - * + *

* Algorithm: MergingIterator maintains a PriorityQueue of PeekFileRecordIterators. * Each PeekFileRecordIterator iterates through a file in which the records are sorted. * The comparator for PeekFileRecordIterator used by the PriorityQueue peeks at the next record from @@ -448,19 +504,47 @@ class MergingIterator implements CloseableIterator { private final TreeSet queue; MergingIterator() { - this.queue = new TreeSet(new PeekFileRecordIteratorComparator()); + this.queue = new TreeSet<>(new PeekFileRecordIteratorComparator()); int n = 0; - for (final Path f : SortingCollection.this.files) { - final FileRecordIterator it = new FileRecordIterator(f); + log.info(String.format("Creating merging iterator from %d files", files.size())); + int suggestedBufferSize = checkMemoryAndAdjustBuffer(files.size()); + for (final Path f : files) { + final FileRecordIterator it = new FileRecordIterator(f, suggestedBufferSize); if (it.hasNext()) { this.queue.add(new PeekFileRecordIterator(it, n++)); - } - else { + } else { it.close(); } } } + // Since we need to open and buffer all temp files in the sorting collection at once it is important + // to have enough memory left to do this. This method checks to make sure that, given the number of files and + // the size of the buffer, we can reasonably open all files. If we can't it will return a buffer size that + // is appropriate given the number of temp files and the amount of memory left on the heap. If there isn't + // enough memory for buffering it will return zero and all reading will be unbuffered. + private int checkMemoryAndAdjustBuffer(int numFiles) { + int bufferSize = Defaults.BUFFER_SIZE; + // garbage collect so that our calculation is accurate. + Runtime.getRuntime().gc(); + + // There is ~20k in overhead per file. + final long freeMemory = Runtime.getRuntime().freeMemory() - (numFiles * 20 * 1024); + // use the floor value from the divide + final int memoryPerFile = (int) (freeMemory / numFiles); + + if (memoryPerFile < 0) { + log.warn("There is not enough memory per file for buffering. Reading will be unbuffered."); + bufferSize = 0; + } else if (bufferSize > memoryPerFile) { + log.warn(String.format("Default io buffer size of %s is larger than available memory per file of %s.", + StringUtil.humanReadableByteCount(bufferSize), + StringUtil.humanReadableByteCount(memoryPerFile))); + bufferSize = memoryPerFile; + } + return bufferSize; + } + @Override public boolean hasNext() { return !this.queue.isEmpty(); @@ -476,9 +560,8 @@ public T next() { final T ret = fileIterator.next(); if (fileIterator.hasNext()) { this.queue.add(fileIterator); - } - else { - ((CloseableIterator)fileIterator.getUnderlyingIterator()).close(); + } else { + ((CloseableIterator) fileIterator.getUnderlyingIterator()).close(); } return ret; @@ -493,7 +576,7 @@ public void remove() { public void close() { while (!this.queue.isEmpty()) { final PeekFileRecordIterator it = this.queue.pollFirst(); - ((CloseableIterator)it.getUnderlyingIterator()).close(); + ((CloseableIterator) it.getUnderlyingIterator()).close(); } } } @@ -507,15 +590,14 @@ class FileRecordIterator implements CloseableIterator { private final Codec codec; private T currentRecord = null; - FileRecordIterator(final Path file) { + FileRecordIterator(final Path file, final int bufferSize) { this.file = file; try { this.is = Files.newInputStream(file); this.codec = SortingCollection.this.codec.clone(); - this.codec.setInputStream(tempStreamFactory.wrapTempInputStream(this.is, Defaults.BUFFER_SIZE)); + this.codec.setInputStream(tempStreamFactory.wrapTempInputStream(this.is, bufferSize)); advance(); - } - catch (IOException e) { + } catch (IOException e) { throw new RuntimeIOException(e); } } @@ -556,6 +638,7 @@ public void close() { */ class PeekFileRecordIterator extends PeekIterator { final int n; // A serial number used for tie-breaking in the sort + PeekFileRecordIterator(final Iterator underlyingIterator, final int n) { super(underlyingIterator); this.n = n; diff --git a/src/main/java/htsjdk/samtools/util/StringUtil.java b/src/main/java/htsjdk/samtools/util/StringUtil.java index a885ba2dbf..acdf869f60 100644 --- a/src/main/java/htsjdk/samtools/util/StringUtil.java +++ b/src/main/java/htsjdk/samtools/util/StringUtil.java @@ -606,4 +606,18 @@ public static boolean isWithinHammingDistance(final String s1, final String s2, } return true; } + + /** + * Takes a long value representing the number of bytes and produces a human readable byte count. + * @param bytes The number of bytes to create a human readable string for. + * @return A human readable string of the number of bytes given. + */ + public static String humanReadableByteCount(long bytes) { + if (bytes < 1024) { + return bytes + " B"; + } + + int exp = (int) (Math.log(bytes) / Math.log(1024)); + return String.format("%.1f %sB", bytes / Math.pow(1024, exp), "kMGTPE".charAt(exp - 1)); + } } diff --git a/src/main/java/htsjdk/samtools/util/ftp/FTPClient.java b/src/main/java/htsjdk/samtools/util/ftp/FTPClient.java index 3af6debc64..c26bb6023e 100644 --- a/src/main/java/htsjdk/samtools/util/ftp/FTPClient.java +++ b/src/main/java/htsjdk/samtools/util/ftp/FTPClient.java @@ -190,9 +190,10 @@ public void closeDataStream() throws IOException { // } catch (InterruptedException e) { // // } - dataStream.close(); - //} - dataStream = null; + if( dataStream != null) { + dataStream.close(); + dataStream = null; + } } diff --git a/src/main/java/htsjdk/samtools/util/nio/DeleteOnExitPathHook.java b/src/main/java/htsjdk/samtools/util/nio/DeleteOnExitPathHook.java new file mode 100644 index 0000000000..ae2a0dd46f --- /dev/null +++ b/src/main/java/htsjdk/samtools/util/nio/DeleteOnExitPathHook.java @@ -0,0 +1,63 @@ +package htsjdk.samtools.util.nio; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; + +/** + * Class to hold a set of {@link Path} to be delete on the JVM exit through a shutdown hook. + * + *

This class is a modification of {@link java.io.DeleteOnExitHook} to handle {@link Path} + * instead of {@link java.io.File}. + * + * @author Daniel Gomez-Sanchez (magicDGS) + */ +public class DeleteOnExitPathHook { + private static LinkedHashSet paths = new LinkedHashSet<>(); + static { + Runtime.getRuntime().addShutdownHook(new Thread(DeleteOnExitPathHook::runHooks)); + } + + private DeleteOnExitPathHook() {} + + /** + * Adds a {@link Path} for deletion on JVM exit. + * + * @param path path to be deleted. + * + * @throws IllegalStateException if the shutdown hook is in progress. + */ + public static synchronized void add(Path path) { + if(paths == null) { + // DeleteOnExitHook is running. Too late to add a file + throw new IllegalStateException("Shutdown in progress"); + } + + paths.add(path); + } + + static void runHooks() { + LinkedHashSet thePaths; + + synchronized (DeleteOnExitPathHook.class) { + thePaths = paths; + paths = null; + } + + ArrayList toBeDeleted = new ArrayList<>(thePaths); + + // reverse the list to maintain previous jdk deletion order. + // Last in first deleted. + Collections.reverse(toBeDeleted); + for (Path path : toBeDeleted) { + try { + Files.delete(path); + } catch (IOException | SecurityException e) { + // do nothing if cannot be deleted, because it is a shutdown hook + } + } + } +} diff --git a/src/main/java/htsjdk/tribble/AbstractFeatureReader.java b/src/main/java/htsjdk/tribble/AbstractFeatureReader.java old mode 100644 new mode 100755 index 511084ef51..958135fe05 --- a/src/main/java/htsjdk/tribble/AbstractFeatureReader.java +++ b/src/main/java/htsjdk/tribble/AbstractFeatureReader.java @@ -18,6 +18,7 @@ package htsjdk.tribble; +import htsjdk.samtools.util.IOUtil; import htsjdk.tribble.index.Index; import htsjdk.tribble.util.ParsingUtils; import htsjdk.tribble.util.TabixUtils; @@ -57,7 +58,9 @@ public abstract class AbstractFeatureReader implement private static ComponentMethods methods = new ComponentMethods(); - public static final Set BLOCK_COMPRESSED_EXTENSIONS = Collections.unmodifiableSet(new HashSet(Arrays.asList(".gz", ".gzip", ".bgz", ".bgzf"))); + /** @deprecated use {@link IOUtil#BLOCK_COMPRESSED_EXTENSIONS} instead. */ + @Deprecated + public static final Set BLOCK_COMPRESSED_EXTENSIONS = IOUtil.BLOCK_COMPRESSED_EXTENSIONS; /** * Calls {@link #getFeatureReader(String, FeatureCodec, boolean)} with {@code requireIndex} = true @@ -170,52 +173,28 @@ public static void setComponentMethods(ComponentMethods methods){ } /** - * Whether a filename ends in one of the BLOCK_COMPRESSED_EXTENSIONS - * @param fileName - * @return + * @deprecated use {@link IOUtil#hasBlockCompressedExtension(String)}. */ + @Deprecated public static boolean hasBlockCompressedExtension (final String fileName) { - String cleanedPath = stripQueryStringIfPathIsAnHttpUrl(fileName); - for (final String extension : BLOCK_COMPRESSED_EXTENSIONS) { - if (cleanedPath.toLowerCase().endsWith(extension)) - return true; - } - return false; - } - - /** - * Remove http query before checking extension - * Path might be a local file, in which case a '?' is a legal part of the filename. - * @param path a string representing some sort of path, potentially an http url - * @return path with no trailing queryString (ex: http://something.com/path.vcf?stuff=something => http://something.com/path.vcf) - */ - private static String stripQueryStringIfPathIsAnHttpUrl(String path) { - if(path.startsWith("http://") || path.startsWith("https://")) { - int qIdx = path.indexOf('?'); - if (qIdx > 0) { - return path.substring(0, qIdx); - } - } - return path; + return IOUtil.hasBlockCompressedExtension(fileName); } /** - * Whether the name of a file ends in one of the BLOCK_COMPRESSED_EXTENSIONS - * @param file - * @return + * @deprecated use {@link IOUtil#hasBlockCompressedExtension(File)}. */ + @Deprecated public static boolean hasBlockCompressedExtension (final File file) { - return hasBlockCompressedExtension(file.getName()); + return IOUtil.hasBlockCompressedExtension(file.getName()); } /** - * Whether the path of a URI resource ends in one of the BLOCK_COMPRESSED_EXTENSIONS - * @param uri a URI representing the resource to check - * @return + * @deprecated use {@link IOUtil#hasBlockCompressedExtension(URI)}. */ + @Deprecated public static boolean hasBlockCompressedExtension (final URI uri) { String path = uri.getPath(); - return hasBlockCompressedExtension(path); + return IOUtil.hasBlockCompressedExtension(path); } /** @@ -240,7 +219,7 @@ public static boolean isTabix(String resourcePath, String indexPath) throws IOEx if(indexPath == null){ indexPath = ParsingUtils.appendToPath(resourcePath, TabixUtils.STANDARD_INDEX_EXTENSION); } - return hasBlockCompressedExtension(resourcePath) && ParsingUtils.resourceExists(indexPath); + return IOUtil.hasBlockCompressedExtension(resourcePath) && ParsingUtils.resourceExists(indexPath); } public static class ComponentMethods{ diff --git a/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java b/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java index 8603431de8..ae847a74ac 100644 --- a/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java +++ b/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java @@ -25,6 +25,7 @@ import htsjdk.samtools.seekablestream.SeekableStream; import htsjdk.samtools.seekablestream.SeekableStreamFactory; +import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.RuntimeIOException; import htsjdk.tribble.index.Block; import htsjdk.tribble.index.Index; @@ -250,7 +251,7 @@ private void readHeader() throws IOException { PositionalBufferedStream pbs = null; try { is = ParsingUtils.openInputStream(path, wrapper); - if (hasBlockCompressedExtension(new URI(URLEncoder.encode(path, "UTF-8")))) { + if (IOUtil.hasBlockCompressedExtension(new URI(URLEncoder.encode(path, "UTF-8")))) { // TODO: TEST/FIX THIS! https://github.com/samtools/htsjdk/issues/944 // TODO -- warning I don't think this can work, the buffered input stream screws up position is = new GZIPInputStream(new BufferedInputStream(is)); @@ -324,7 +325,7 @@ public WFIterator() throws IOException { final InputStream inputStream = ParsingUtils.openInputStream(path, wrapper); final PositionalBufferedStream pbs; - if (hasBlockCompressedExtension(path)) { + if (IOUtil.hasBlockCompressedExtension(path)) { // Gzipped -- we need to buffer the GZIPInputStream methods as this class makes read() calls, // and seekableStream does not support single byte reads final InputStream is = new GZIPInputStream(new BufferedInputStream(inputStream, 512000)); diff --git a/src/main/java/htsjdk/tribble/bed/BEDCodec.java b/src/main/java/htsjdk/tribble/bed/BEDCodec.java index 2ee4be7e6d..7433c350d1 100644 --- a/src/main/java/htsjdk/tribble/bed/BEDCodec.java +++ b/src/main/java/htsjdk/tribble/bed/BEDCodec.java @@ -23,6 +23,7 @@ */ package htsjdk.tribble.bed; +import htsjdk.samtools.util.IOUtil; import htsjdk.tribble.AbstractFeatureReader; import htsjdk.tribble.AsciiFeatureCodec; import htsjdk.tribble.annotation.Strand; @@ -229,7 +230,7 @@ private void createExons(int start, String[] tokens, FullBEDFeature gene, @Override public boolean canDecode(final String path) { final String toDecode; - if (AbstractFeatureReader.hasBlockCompressedExtension(path)) { + if (IOUtil.hasBlockCompressedExtension(path)) { toDecode = path.substring(0, path.lastIndexOf(".")); } else { toDecode = path; diff --git a/src/main/java/htsjdk/tribble/index/AbstractIndex.java b/src/main/java/htsjdk/tribble/index/AbstractIndex.java index ac90e5d2ba..256e6716a6 100644 --- a/src/main/java/htsjdk/tribble/index/AbstractIndex.java +++ b/src/main/java/htsjdk/tribble/index/AbstractIndex.java @@ -142,7 +142,7 @@ public boolean equalsIgnoreProperties(final Object obj) { } if (!chrIndices.equals(other.chrIndices)) { - System.err.printf("equals chrIndeces: this %s != other %s%n", chrIndices, other.chrIndices); + System.err.printf("equals chrIndices: this %s != other %s%n", chrIndices, other.chrIndices); return false; } @@ -173,7 +173,7 @@ public AbstractIndex(final String featureFile) { } public AbstractIndex(final File featureFile) { - this(featureFile.toPath()); + this(IOUtil.toPath(featureFile)); } public AbstractIndex(final Path featurePath) { diff --git a/src/main/java/htsjdk/tribble/index/DynamicIndexCreator.java b/src/main/java/htsjdk/tribble/index/DynamicIndexCreator.java index 17274ace68..0d3fb921cb 100644 --- a/src/main/java/htsjdk/tribble/index/DynamicIndexCreator.java +++ b/src/main/java/htsjdk/tribble/index/DynamicIndexCreator.java @@ -24,6 +24,7 @@ package htsjdk.tribble.index; +import htsjdk.samtools.util.IOUtil; import htsjdk.tribble.Feature; import htsjdk.tribble.TribbleException; import htsjdk.tribble.index.interval.IntervalIndexCreator; @@ -65,7 +66,7 @@ public DynamicIndexCreator(final Path inputPath, final IndexFactory.IndexBalance } public DynamicIndexCreator(final File inputFile, final IndexFactory.IndexBalanceApproach iba) { - this(inputFile.toPath(), iba); + this(IOUtil.toPath(inputFile), iba); } @Override diff --git a/src/main/java/htsjdk/tribble/index/Index.java b/src/main/java/htsjdk/tribble/index/Index.java index 51982c6d28..be1b697e85 100644 --- a/src/main/java/htsjdk/tribble/index/Index.java +++ b/src/main/java/htsjdk/tribble/index/Index.java @@ -23,6 +23,7 @@ */ package htsjdk.tribble.index; +import htsjdk.samtools.util.IOUtil; import htsjdk.tribble.util.LittleEndianOutputStream; import java.io.File; @@ -79,7 +80,7 @@ public interface Index { * @throws IOException if the index is unable to write to the specified file */ public default void write(final File idxFile) throws IOException { - write(idxFile.toPath()); + write(IOUtil.toPath(idxFile)); } /** @@ -99,7 +100,7 @@ public default void write(final File idxFile) throws IOException { * @throws IOException if featureFile is not a normal file. */ public default void writeBasedOnFeatureFile(File featureFile) throws IOException { - writeBasedOnFeaturePath(featureFile.toPath()); + writeBasedOnFeaturePath(IOUtil.toPath(featureFile)); } /** diff --git a/src/main/java/htsjdk/tribble/index/IndexFactory.java b/src/main/java/htsjdk/tribble/index/IndexFactory.java index 6007cf194c..1c9aee1df0 100644 --- a/src/main/java/htsjdk/tribble/index/IndexFactory.java +++ b/src/main/java/htsjdk/tribble/index/IndexFactory.java @@ -162,7 +162,7 @@ public static IndexType getIndexType(final BufferedInputStream is) { * @param indexFile from which to load the index */ public static Index loadIndex(final String indexFile) { - return loadIndex(indexFile, null); + return loadIndex(indexFile, (Function) null); } /** @@ -174,18 +174,30 @@ public static Index loadIndex(final String indexFile) { * {@link java.nio.file.Path} */ public static Index loadIndex(final String indexFile, Function indexWrapper) { + try { + return loadIndex(indexFile, indexFileInputStream(indexFile, indexWrapper)); + } catch (final IOException ex) { + throw new TribbleException.UnableToReadIndexFile("Unable to read index file", indexFile, ex); + } + } + + /** + * Load in index from the specified stream. Note that the caller is responsible for decompressing the stream if necessary. + * + * @param source the stream source (typically the file name) + * @param inputStream the raw byte stream of the index + */ + public static Index loadIndex(final String source, final InputStream inputStream) { // Must be buffered, because getIndexType uses mark and reset - try (BufferedInputStream bufferedInputStream = new BufferedInputStream(indexFileInputStream(indexFile, indexWrapper), Defaults.NON_ZERO_BUFFER_SIZE)) { + try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream, Defaults.NON_ZERO_BUFFER_SIZE)) { final Class indexClass = IndexType.getIndexType(bufferedInputStream).getIndexType(); final Constructor ctor = indexClass.getConstructor(InputStream.class); return ctor.newInstance(bufferedInputStream); } catch (final TribbleException ex) { throw ex; - } catch (final IOException ex) { - throw new TribbleException.UnableToReadIndexFile("Unable to read index file", indexFile, ex); } catch (final InvocationTargetException ex) { if (ex.getCause() instanceof EOFException) { - throw new TribbleException.CorruptedIndexFile("Index file is corrupted", indexFile, ex); + throw new TribbleException.CorruptedIndexFile("Index file is corrupted", source, ex); } throw new RuntimeException(ex); } catch (final Exception ex) { @@ -429,7 +441,7 @@ public FeatureIterator(final File inputFile, final FeatureCodec indices, final Path featureFile) { * @param featureFile */ public LinearIndex(final List indices, final File featureFile) { - this(indices, featureFile.toPath()); + this(indices, IOUtil.toPath(featureFile)); } private LinearIndex(final LinearIndex parent, final List indices) { diff --git a/src/main/java/htsjdk/tribble/index/linear/LinearIndexCreator.java b/src/main/java/htsjdk/tribble/index/linear/LinearIndexCreator.java index 9109705d25..c4ff04da36 100644 --- a/src/main/java/htsjdk/tribble/index/linear/LinearIndexCreator.java +++ b/src/main/java/htsjdk/tribble/index/linear/LinearIndexCreator.java @@ -23,6 +23,7 @@ */ package htsjdk.tribble.index.linear; +import htsjdk.samtools.util.IOUtil; import htsjdk.tribble.Feature; import htsjdk.tribble.index.Block; import htsjdk.tribble.index.Index; @@ -57,11 +58,11 @@ public LinearIndexCreator(final Path inputPath, final int binSize) { } public LinearIndexCreator(final File inputFile, final int binSize) { - this(inputFile.toPath(), binSize); + this(IOUtil.toPath(inputFile), binSize); } public LinearIndexCreator(final File inputFile) { - this(inputFile.toPath()); + this(IOUtil.toPath(inputFile)); } public LinearIndexCreator(final Path inputPath) { diff --git a/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java b/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java index d7cc31cef6..6c27b363e2 100644 --- a/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java +++ b/src/main/java/htsjdk/tribble/index/tabix/TabixIndex.java @@ -215,7 +215,7 @@ public TabixFormat getFormatSpec() { */ @Override public void write(final Path tabixPath) throws IOException { - try(final LittleEndianOutputStream los = new LittleEndianOutputStream(new BlockCompressedOutputStream(Files.newOutputStream(tabixPath), null))) { + try(final LittleEndianOutputStream los = new LittleEndianOutputStream(new BlockCompressedOutputStream(Files.newOutputStream(tabixPath), (Path)null))) { write(los); } } diff --git a/src/main/java/htsjdk/variant/utils/VCFHeaderReader.java b/src/main/java/htsjdk/variant/utils/VCFHeaderReader.java new file mode 100644 index 0000000000..b274c29e42 --- /dev/null +++ b/src/main/java/htsjdk/variant/utils/VCFHeaderReader.java @@ -0,0 +1,61 @@ +package htsjdk.variant.utils; + +import htsjdk.samtools.SamStreams; +import htsjdk.samtools.cram.io.InputStreamUtils; +import htsjdk.samtools.seekablestream.SeekableStream; +import htsjdk.tribble.Feature; +import htsjdk.tribble.FeatureCodec; +import htsjdk.tribble.FeatureCodecHeader; +import htsjdk.tribble.TribbleException; +import htsjdk.variant.bcf2.BCF2Codec; +import htsjdk.variant.bcf2.BCFVersion; +import htsjdk.variant.vcf.VCFCodec; +import htsjdk.variant.vcf.VCFHeader; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.zip.GZIPInputStream; + +/** + * Utility class to read a VCF header without being told beforehand whether the input is VCF or BCF. + */ +public final class VCFHeaderReader { + + private VCFHeaderReader(){} + + /** + * Read a VCF header from a stream that may be a VCF file (possibly gzip or block compressed) or a BCF file. + * After successfully reading a header the stream is positioned immediately after the header, otherwise, if an + * exception is thrown, the state of the stream is undefined. + * + * @param in the stream to read the header from + * @return the VCF header read from the stream + * @throws TribbleException.InvalidHeader if the header in the file is invalid + * @throws IOException if an IOException occurs while reading the header + */ + public static VCFHeader readHeaderFrom(final SeekableStream in) throws IOException { + final long initialPos = in.position(); + byte[] magicBytes = InputStreamUtils.readFully(bufferAndDecompressIfNecessary(in), BCFVersion.MAGIC_HEADER_START.length); + in.seek(initialPos); + if (magicBytes[0] == '#') { // VCF + return readHeaderFrom(in, new VCFCodec()); + } else if (Arrays.equals(magicBytes, BCFVersion.MAGIC_HEADER_START)) { + return readHeaderFrom(in, new BCF2Codec()); + } + throw new TribbleException.InvalidHeader("No VCF header found in " + in.getSource()); + } + + private static InputStream bufferAndDecompressIfNecessary(final InputStream in) throws IOException { + BufferedInputStream bis = new BufferedInputStream(in); + // despite the name, SamStreams.isGzippedSAMFile looks for any gzipped stream (including block compressed) + return SamStreams.isGzippedSAMFile(bis) ? new GZIPInputStream(bis) : bis; + } + + private static VCFHeader readHeaderFrom(final InputStream in, final FeatureCodec featureCodec) throws IOException { + InputStream is = bufferAndDecompressIfNecessary(in); + FeatureCodecHeader headerCodec = featureCodec.readHeader(featureCodec.makeSourceFromStream(is)); + return (VCFHeader) headerCodec.getHeaderValue(); + } +} diff --git a/src/main/java/htsjdk/variant/variantcontext/Allele.java b/src/main/java/htsjdk/variant/variantcontext/Allele.java index abfda8b325..dfd11d892f 100644 --- a/src/main/java/htsjdk/variant/variantcontext/Allele.java +++ b/src/main/java/htsjdk/variant/variantcontext/Allele.java @@ -26,7 +26,6 @@ package htsjdk.variant.variantcontext; import htsjdk.samtools.util.StringUtil; -import htsjdk.variant.vcf.VCFConstants; import java.io.Serializable; import java.util.Arrays; @@ -200,6 +199,16 @@ protected Allele(final Allele allele, final boolean ignoreRefState) { public final static Allele NO_CALL = new Allele(NO_CALL_STRING, false); public final static Allele NON_REF_ALLELE = new Allele(NON_REF_STRING, false); + // for simple deletion, e.g. "ALT==" (note that the spec allows, for now at least, alt alleles like ) + public final static Allele SV_SIMPLE_DEL = StructuralVariantType.DEL.toSymbolicAltAllele(); + // for simple insertion, e.g. "ALT==" + public final static Allele SV_SIMPLE_INS = StructuralVariantType.INS.toSymbolicAltAllele(); + // for simple inversion, e.g. "ALT==" + public final static Allele SV_SIMPLE_INV = StructuralVariantType.INV.toSymbolicAltAllele(); + // for simple generic cnv, e.g. "ALT==" + public final static Allele SV_SIMPLE_CNV = StructuralVariantType.CNV.toSymbolicAltAllele(); + // for simple duplication, e.g. "ALT==" + public final static Allele SV_SIMPLE_DUP = StructuralVariantType.DUP.toSymbolicAltAllele(); // --------------------------------------------------------------------------------------------------------- // diff --git a/src/main/java/htsjdk/variant/variantcontext/GenotypeLikelihoods.java b/src/main/java/htsjdk/variant/variantcontext/GenotypeLikelihoods.java index 605f2985f5..ddaaf55e3e 100644 --- a/src/main/java/htsjdk/variant/variantcontext/GenotypeLikelihoods.java +++ b/src/main/java/htsjdk/variant/variantcontext/GenotypeLikelihoods.java @@ -567,13 +567,26 @@ public static GenotypeLikelihoodsAllelePair getAllelePairUsingDeprecatedOrdering } /** - * get the PL indexes (AA, AB, BB) for the given allele pair; assumes allele1Index <= allele2Index. + * get the PL indices (AA, AB, BB) for the given allele pair; assumes allele1Index <= allele2Index. * * @param allele1Index the index in VariantContext.getAllele() of the first allele * @param allele2Index the index in VariantContext.getAllele() of the second allele * @return the PL indexes + * @deprecated 7/18 use {@link #getPLIndicesOfAlleles(int, int)} instead */ + @Deprecated public static int[] getPLIndecesOfAlleles(final int allele1Index, final int allele2Index) { + return getPLIndicesOfAlleles(allele1Index, allele2Index); + } + + /** + * get the PL indices (AA, AB, BB) for the given allele pair; assumes allele1Index <= allele2Index. + * + * @param allele1Index the index in VariantContext.getAllele() of the first allele + * @param allele2Index the index in VariantContext.getAllele() of the second allele + * @return the PL indexes + */ + public static int[] getPLIndicesOfAlleles(final int allele1Index, final int allele2Index) { final int[] indexes = new int[3]; indexes[0] = calculatePLindex(allele1Index, allele1Index); diff --git a/src/main/java/htsjdk/variant/variantcontext/StructuralVariantType.java b/src/main/java/htsjdk/variant/variantcontext/StructuralVariantType.java index 36b517a2a9..487f089e59 100644 --- a/src/main/java/htsjdk/variant/variantcontext/StructuralVariantType.java +++ b/src/main/java/htsjdk/variant/variantcontext/StructuralVariantType.java @@ -43,5 +43,18 @@ public enum StructuralVariantType { * event can be summarized as a set of novel adjacencies. * Each adjacency ties together two breakends. */ - BND + BND; + + // TODO: 10/10/18 one caveat: BND's have symbolic alt allele, but it takes more information (novel adjacency at the minimum) + /** + * Create angle-bracketed alt allele for simple SV types + * @return angle-bracketed alt allele for simple SV types + * @throws UnsupportedOperationException if this is invoked on a {@link #BND} object + */ + Allele toSymbolicAltAllele() { + if (this.equals(StructuralVariantType.BND)) { + throw new UnsupportedOperationException("BND type does not have angle bracketed alt allele"); + } + return Allele.create("<" + name() + ">", false); + } } diff --git a/src/main/java/htsjdk/variant/variantcontext/VariantContext.java b/src/main/java/htsjdk/variant/variantcontext/VariantContext.java index 6def89ef9c..46b124496d 100644 --- a/src/main/java/htsjdk/variant/variantcontext/VariantContext.java +++ b/src/main/java/htsjdk/variant/variantcontext/VariantContext.java @@ -25,6 +25,7 @@ package htsjdk.variant.variantcontext; +import htsjdk.samtools.util.Locatable; import htsjdk.tribble.Feature; import htsjdk.tribble.TribbleException; import htsjdk.tribble.util.ParsingUtils; @@ -215,7 +216,6 @@ * asking for a fully decoded version of the VC. * * - * @author depristo */ public class VariantContext implements Feature, Serializable { public static final long serialVersionUID = 1L; @@ -1448,32 +1448,35 @@ public String toString() { } public String toStringDecodeGenotypes() { - return String.format("[VC %s @ %s Q%s of type=%s alleles=%s attr=%s GT=%s", + return String.format("[VC %s @ %s Q%s of type=%s alleles=%s attr=%s GT=%s filters=%s", getSource(), contig + ":" + (start - stop == 0 ? start : start + "-" + stop), hasLog10PError() ? String.format("%.2f", getPhredScaledQual()) : ".", this.getType(), ParsingUtils.sortList(this.getAlleles()), ParsingUtils.sortedString(this.getAttributes()), - this.getGenotypes()); + this.getGenotypes(), + String.join(",", commonInfo.getFilters())); } private String toStringUnparsedGenotypes() { - return String.format("[VC %s @ %s Q%s of type=%s alleles=%s attr=%s GT=%s", + return String.format("[VC %s @ %s Q%s of type=%s alleles=%s attr=%s GT=%s filters=%s", getSource(), contig + ":" + (start - stop == 0 ? start : start + "-" + stop), hasLog10PError() ? String.format("%.2f", getPhredScaledQual()) : ".", this.getType(), ParsingUtils.sortList(this.getAlleles()), ParsingUtils.sortedString(this.getAttributes()), - ((LazyGenotypesContext)this.genotypes).getUnparsedGenotypeData()); + ((LazyGenotypesContext)this.genotypes).getUnparsedGenotypeData(), + String.join(",", commonInfo.getFilters())); } public String toStringWithoutGenotypes() { - return String.format("[VC %s @ %s Q%s of type=%s alleles=%s attr=%s", + return String.format("[VC %s @ %s Q%s of type=%s alleles=%s attr=%s filters=%s", getSource(), contig + ":" + (start - stop == 0 ? start : start + "-" + stop), hasLog10PError() ? String.format("%.2f", getPhredScaledQual()) : ".", this.getType(), ParsingUtils.sortList(this.getAlleles()), - ParsingUtils.sortedString(this.getAttributes())); + ParsingUtils.sortedString(this.getAttributes()), + String.join(",", commonInfo.getFilters())); } // protected basic manipulation routines @@ -1719,12 +1722,20 @@ public List getAlleleIndices(final Collection alleles) { .collect(Collectors.toCollection(() -> new ArrayList<>(alleles.size()))); } + /** + * @deprecated 7/18 use {@link #getGLIndicesOfAlternateAllele(Allele)} instead + */ + @Deprecated public int[] getGLIndecesOfAlternateAllele(Allele targetAllele) { + return getGLIndicesOfAlternateAllele(targetAllele); + } + + public int[] getGLIndicesOfAlternateAllele(Allele targetAllele) { final int index = getAlleleIndex(targetAllele); if ( index == -1 ) throw new IllegalArgumentException("Allele " + targetAllele + " not in this VariantContex " + this); - return GenotypeLikelihoods.getPLIndecesOfAlleles(0, index); + return GenotypeLikelihoods.getPLIndicesOfAlleles(0, index); } - + /** * Search for the INFO=SVTYPE and return the type of Structural Variant * @return the StructuralVariantType of null if there is no property SVTYPE diff --git a/src/main/java/htsjdk/variant/variantcontext/writer/BCF2Writer.java b/src/main/java/htsjdk/variant/variantcontext/writer/BCF2Writer.java index cf578d8069..07b2d0d41e 100644 --- a/src/main/java/htsjdk/variant/variantcontext/writer/BCF2Writer.java +++ b/src/main/java/htsjdk/variant/variantcontext/writer/BCF2Writer.java @@ -26,6 +26,7 @@ package htsjdk.variant.variantcontext.writer; import htsjdk.samtools.SAMSequenceDictionary; +import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.RuntimeIOException; import htsjdk.tribble.index.IndexCreator; import htsjdk.variant.bcf2.BCF2Codec; @@ -49,6 +50,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -128,12 +130,24 @@ class BCF2Writer extends IndexingVariantContextWriter { public BCF2Writer(final File location, final OutputStream output, final SAMSequenceDictionary refDict, final boolean enableOnTheFlyIndexing, final boolean doNotWriteGenotypes) { + this(IOUtil.toPath(location), output, refDict, enableOnTheFlyIndexing, doNotWriteGenotypes); + } + + public BCF2Writer(final Path location, final OutputStream output, final SAMSequenceDictionary refDict, + final boolean enableOnTheFlyIndexing, final boolean doNotWriteGenotypes) { super(writerName(location, output), location, output, refDict, enableOnTheFlyIndexing); this.outputStream = getOutputStream(); this.doNotWriteGenotypes = doNotWriteGenotypes; } public BCF2Writer(final File location, final OutputStream output, final SAMSequenceDictionary refDict, + final IndexCreator indexCreator, + final boolean enableOnTheFlyIndexing, final boolean doNotWriteGenotypes) { + this(IOUtil.toPath(location), output, refDict, indexCreator, enableOnTheFlyIndexing, + doNotWriteGenotypes); + } + + public BCF2Writer(final Path location, final OutputStream output, final SAMSequenceDictionary refDict, final IndexCreator indexCreator, final boolean enableOnTheFlyIndexing, final boolean doNotWriteGenotypes) { super(writerName(location, output), location, output, refDict, enableOnTheFlyIndexing, indexCreator); diff --git a/src/main/java/htsjdk/variant/variantcontext/writer/IndexingVariantContextWriter.java b/src/main/java/htsjdk/variant/variantcontext/writer/IndexingVariantContextWriter.java index fa3f6ba54c..264f7beb92 100644 --- a/src/main/java/htsjdk/variant/variantcontext/writer/IndexingVariantContextWriter.java +++ b/src/main/java/htsjdk/variant/variantcontext/writer/IndexingVariantContextWriter.java @@ -26,6 +26,7 @@ package htsjdk.variant.variantcontext.writer; import htsjdk.samtools.SAMSequenceDictionary; +import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.LocationAware; import htsjdk.samtools.util.RuntimeIOException; import htsjdk.tribble.index.DynamicIndexCreator; @@ -40,20 +41,21 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; +import java.nio.file.Path; /** * this class writes VCF files */ abstract class IndexingVariantContextWriter implements VariantContextWriter { private final String name; - private final File location; + private final Path location; private final SAMSequenceDictionary refDict; private OutputStream outputStream; private LocationAware locationSource = null; private IndexCreator indexer = null; - private IndexingVariantContextWriter(final String name, final File location, final OutputStream output, final SAMSequenceDictionary refDict) { + private IndexingVariantContextWriter(final String name, final Path location, final OutputStream output, final SAMSequenceDictionary refDict) { this.name = name; this.location = location; this.outputStream = output; @@ -73,6 +75,20 @@ private IndexingVariantContextWriter(final String name, final File location, fin */ protected IndexingVariantContextWriter(final String name, final File location, final OutputStream output, final SAMSequenceDictionary refDict, final boolean enableOnTheFlyIndexing) { + this(name, IOUtil.toPath(location), output, refDict, enableOnTheFlyIndexing); + } + + /** + * Create a VariantContextWriter with an associated index using the default index creator + * + * @param name the name of this writer (i.e. the file name or stream) + * @param location the path to the output file + * @param output the output stream to write to + * @param refDict the reference dictionary + * @param enableOnTheFlyIndexing is OTF indexing enabled? + */ + protected IndexingVariantContextWriter(final String name, final Path location, final OutputStream output, final SAMSequenceDictionary refDict, + final boolean enableOnTheFlyIndexing) { this(name, location, output, refDict); if ( enableOnTheFlyIndexing ) { @@ -92,6 +108,21 @@ protected IndexingVariantContextWriter(final String name, final File location, f */ protected IndexingVariantContextWriter(final String name, final File location, final OutputStream output, final SAMSequenceDictionary refDict, final boolean enableOnTheFlyIndexing, final IndexCreator idxCreator) { + this(name, IOUtil.toPath(location), output, refDict, enableOnTheFlyIndexing, idxCreator); + } + + /** + * Create a VariantContextWriter with an associated index using a custom index creator + * + * @param name the name of this writer (i.e. the file name or stream) + * @param location the path to the output file + * @param output the output stream to write to + * @param refDict the reference dictionary + * @param enableOnTheFlyIndexing is OTF indexing enabled? + * @param idxCreator the custom index creator. NOTE: must be initialized + */ + protected IndexingVariantContextWriter(final String name, final Path location, final OutputStream output, final SAMSequenceDictionary refDict, + final boolean enableOnTheFlyIndexing, final IndexCreator idxCreator) { this(name, location, output, refDict); if ( enableOnTheFlyIndexing ) { @@ -144,7 +175,7 @@ public void close() { if (indexer != null) { indexer.setIndexSequenceDictionary(refDict); final Index index = indexer.finalizeIndex(locationSource.getPosition()); - index.writeBasedOnFeatureFile(location); + index.writeBasedOnFeaturePath(location); } @@ -180,6 +211,17 @@ public void add(final VariantContext vc) { * @return */ protected static final String writerName(final File location, final OutputStream stream) { - return location == null ? stream == null ? DEFAULT_READER_NAME : stream.toString() : location.getAbsolutePath(); + return writerName(IOUtil.toPath(location), stream); + } + + /** + * Returns a reasonable "name" for this writer, to display to the user if something goes wrong + * + * @param location + * @param stream + * @return + */ + protected static final String writerName(final Path location, final OutputStream stream) { + return location == null ? stream == null ? DEFAULT_READER_NAME : stream.toString() : location.toAbsolutePath().toUri().toString(); } } diff --git a/src/main/java/htsjdk/variant/variantcontext/writer/VCFWriter.java b/src/main/java/htsjdk/variant/variantcontext/writer/VCFWriter.java index 442567b9fd..742b1c8929 100644 --- a/src/main/java/htsjdk/variant/variantcontext/writer/VCFWriter.java +++ b/src/main/java/htsjdk/variant/variantcontext/writer/VCFWriter.java @@ -26,6 +26,7 @@ package htsjdk.variant.variantcontext.writer; import htsjdk.samtools.SAMSequenceDictionary; +import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.RuntimeIOException; import htsjdk.tribble.index.IndexCreator; import htsjdk.variant.variantcontext.VariantContext; @@ -43,6 +44,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.file.Path; /** * this class writes VCF files @@ -86,6 +88,14 @@ public VCFWriter(final File location, final OutputStream output, final SAMSequen final boolean enableOnTheFlyIndexing, final boolean doNotWriteGenotypes, final boolean allowMissingFieldsInHeader, final boolean writeFullFormatField) { + this(IOUtil.toPath(location), output, refDict, enableOnTheFlyIndexing, doNotWriteGenotypes, + allowMissingFieldsInHeader,writeFullFormatField); + } + + public VCFWriter(final Path location, final OutputStream output, final SAMSequenceDictionary refDict, + final boolean enableOnTheFlyIndexing, + final boolean doNotWriteGenotypes, final boolean allowMissingFieldsInHeader, + final boolean writeFullFormatField) { super(writerName(location, output), location, output, refDict, enableOnTheFlyIndexing); this.doNotWriteGenotypes = doNotWriteGenotypes; this.allowMissingFieldsInHeader = allowMissingFieldsInHeader; @@ -96,11 +106,20 @@ public VCFWriter(final File location, final OutputStream output, final SAMSequen final IndexCreator indexCreator, final boolean enableOnTheFlyIndexing, final boolean doNotWriteGenotypes, final boolean allowMissingFieldsInHeader, final boolean writeFullFormatField) { + this(IOUtil.toPath(location), output, refDict, indexCreator, enableOnTheFlyIndexing, + doNotWriteGenotypes, allowMissingFieldsInHeader, writeFullFormatField); + } + + public VCFWriter(final Path location, final OutputStream output, final SAMSequenceDictionary refDict, + final IndexCreator indexCreator, final boolean enableOnTheFlyIndexing, + final boolean doNotWriteGenotypes, final boolean allowMissingFieldsInHeader, + final boolean writeFullFormatField) { super(writerName(location, output), location, output, refDict, enableOnTheFlyIndexing, indexCreator); this.doNotWriteGenotypes = doNotWriteGenotypes; this.allowMissingFieldsInHeader = allowMissingFieldsInHeader; this.writeFullFormatField = writeFullFormatField; } + // -------------------------------------------------------------------------------- // // VCFWriter interface functions @@ -219,9 +238,15 @@ public void close() { public void add(final VariantContext context) { try { super.add(context); - - if (this.doNotWriteGenotypes) write(this.vcfEncoder.encode(new VariantContextBuilder(context).noGenotypes().make())); - else write(this.vcfEncoder.encode(context)); + if (this.mHeader == null) { + throw new IllegalStateException("Unable to write the VCF: header is missing, " + + "try to call writeHeader or setHeader first."); + } + if (this.doNotWriteGenotypes) { + this.vcfEncoder.write(this.writer, new VariantContextBuilder(context).noGenotypes().make()); + } else { + this.vcfEncoder.write(this.writer, context); + } write("\n"); writeAndResetBuffer(); diff --git a/src/main/java/htsjdk/variant/variantcontext/writer/VariantContextWriterBuilder.java b/src/main/java/htsjdk/variant/variantcontext/writer/VariantContextWriterBuilder.java index e9038e9868..d809d3aff0 100644 --- a/src/main/java/htsjdk/variant/variantcontext/writer/VariantContextWriterBuilder.java +++ b/src/main/java/htsjdk/variant/variantcontext/writer/VariantContextWriterBuilder.java @@ -31,15 +31,17 @@ import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.Md5CalculatingOutputStream; import htsjdk.samtools.util.RuntimeIOException; -import htsjdk.tribble.AbstractFeatureReader; import htsjdk.tribble.index.IndexCreator; import htsjdk.tribble.index.tabix.TabixFormat; import htsjdk.tribble.index.tabix.TabixIndexCreator; import java.io.File; import java.io.FileNotFoundException; -import java.io.FileOutputStream; +import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.OpenOption; +import java.nio.file.Path; import java.util.EnumSet; /* @@ -104,6 +106,7 @@ public class VariantContextWriterBuilder { public static final EnumSet DEFAULT_OPTIONS = EnumSet.of(Options.INDEX_ON_THE_FLY); public static final EnumSet NO_OPTIONS = EnumSet.noneOf(Options.class); + private static final OpenOption[] EMPTY_OPEN_OPTION_ARRAY = new OpenOption[0]; public enum OutputType { UNSPECIFIED, @@ -119,7 +122,7 @@ public enum OutputType { private SAMSequenceDictionary refDict = null; private OutputType outType = OutputType.UNSPECIFIED; - private File outFile = null; + private Path outPath = null; private OutputStream outStream = null; private IndexCreator idxCreator = null; private int bufferSize = Defaults.BUFFER_SIZE; @@ -154,9 +157,20 @@ public VariantContextWriterBuilder setReferenceDictionary(final SAMSequenceDicti * @return this VariantContextWriterBuilder */ public VariantContextWriterBuilder setOutputFile(final File outFile) { - this.outFile = outFile; + return setOutputPath(IOUtil.toPath(outFile)); + } + + /** + * Set the output file for the next VariantContextWriter created by this builder. + * Determines file type implicitly from the filename. + * + * @param outPath the file the VariantContextWriter will write to + * @return this VariantContextWriterBuilder + */ + public VariantContextWriterBuilder setOutputPath(final Path outPath) { + this.outPath = outPath; this.outStream = null; - this.outType = determineOutputTypeFromFile(outFile); + this.outType = determineOutputTypeFromFile(outPath); return this; } @@ -181,7 +195,7 @@ public VariantContextWriterBuilder setOutputFileType(final OutputType outType) { if (!FILE_TYPES.contains(outType)) throw new IllegalArgumentException("Must choose a file type, not other output types."); - if (this.outFile == null || this.outStream != null) + if (this.outPath == null || this.outStream != null) throw new IllegalArgumentException("Cannot set a file type if the output is not to a file."); this.outType = outType; @@ -197,7 +211,7 @@ public VariantContextWriterBuilder setOutputFileType(final OutputType outType) { */ public VariantContextWriterBuilder setOutputVCFStream(final OutputStream outStream) { this.outStream = outStream; - this.outFile = null; + this.outPath = null; this.outType = OutputType.VCF_STREAM; return this; } @@ -211,7 +225,7 @@ public VariantContextWriterBuilder setOutputVCFStream(final OutputStream outStre */ public VariantContextWriterBuilder setOutputBCFStream(final OutputStream outStream) { this.outStream = outStream; - this.outFile = null; + this.outPath = null; this.outType = OutputType.BCF_STREAM; return this; } @@ -384,16 +398,33 @@ boolean isOptionSet(final Options option) { return this.options.contains(option); } + /** * Validate and build the VariantContextWriter. * - * @return the VariantContextWriter as specified by previous method calls + * @return the VariantContextWriter as specified by previous method calls. * @throws RuntimeIOException if the writer is configured to write to a file, and the corresponding path does not exist. * @throws IllegalArgumentException if no output file or stream is specified. * @throws IllegalArgumentException if Options.INDEX_ON_THE_FLY is specified and no reference dictionary is provided. * @throws IllegalArgumentException if Options.INDEX_ON_THE_FLY is specified and a stream output is specified. */ public VariantContextWriter build() { + return build(EMPTY_OPEN_OPTION_ARRAY); + } + + /** + * Validate and build the VariantContextWriter. + * + * @param openOptions options to use when opening the underlying output stream. + * + * @return the VariantContextWriter as specified by previous method calls, + * optionally applying the specified OpenOptions. + * @throws RuntimeIOException if the writer is configured to write to a file, and the corresponding path does not exist. + * @throws IllegalArgumentException if no output file or stream is specified. + * @throws IllegalArgumentException if Options.INDEX_ON_THE_FLY is specified and no reference dictionary is provided. + * @throws IllegalArgumentException if Options.INDEX_ON_THE_FLY is specified and a stream output is specified. + */ + public VariantContextWriter build(OpenOption... openOptions) { VariantContextWriter writer = null; // don't allow FORCE_BCF to modify the outType state @@ -410,13 +441,14 @@ else if (STREAM_TYPES.contains(this.outType)) OutputStream outStreamFromFile = this.outStream; if (FILE_TYPES.contains(this.outType) || (STREAM_TYPES.contains(this.outType) && this.outStream == null)) { try { - outStreamFromFile = IOUtil.maybeBufferOutputStream(new FileOutputStream(outFile), bufferSize); + outStreamFromFile = IOUtil.maybeBufferOutputStream(Files.newOutputStream(outPath, openOptions), bufferSize); } catch (final FileNotFoundException e) { - throw new RuntimeIOException("File not found: " + outFile, e); + throw new RuntimeIOException("File not found: " + outPath, e); + } catch (final IOException e) { + throw new RuntimeIOException("File not found: " + outPath, e); } - if (createMD5) - outStreamFromFile = new Md5CalculatingOutputStream(outStreamFromFile, new File(outFile.getAbsolutePath() + ".md5")); + outStreamFromFile = new Md5CalculatingOutputStream(outStreamFromFile, IOUtil.addExtension(outPath, ".md5")); } switch (typeToBuild) { @@ -426,7 +458,7 @@ else if (STREAM_TYPES.contains(this.outType)) if ((refDict == null) && (options.contains(Options.INDEX_ON_THE_FLY))) throw new IllegalArgumentException("A reference dictionary is required for creating Tribble indices on the fly"); - writer = createVCFWriter(outFile, outStreamFromFile); + writer = createVCFWriter(outPath, outStreamFromFile); break; case BLOCK_COMPRESSED_VCF: if (refDict == null) @@ -434,13 +466,14 @@ else if (STREAM_TYPES.contains(this.outType)) else idxCreator = new TabixIndexCreator(refDict, TabixFormat.VCF); - writer = createVCFWriter(outFile, new BlockCompressedOutputStream(outStreamFromFile, outFile)); + writer = createVCFWriter( + outPath, new BlockCompressedOutputStream(outStreamFromFile, outPath)); break; case BCF: if ((refDict == null) && (options.contains(Options.INDEX_ON_THE_FLY))) throw new IllegalArgumentException("A reference dictionary is required for creating Tribble indices on the fly"); - writer = createBCFWriter(outFile, outStreamFromFile); + writer = createBCFWriter(outPath, outStreamFromFile); break; case VCF_STREAM: if (options.contains(Options.INDEX_ON_THE_FLY)) @@ -467,22 +500,45 @@ else if (STREAM_TYPES.contains(this.outType)) * written to. Will attempt to determine using the logical filename; if that fails it will * attempt to resolve any symlinks and try again. If that fails, and the output file exists * but is neither a file or directory then VCF_STREAM is returned. + * + * @param file A file whose {@link OutputType} we want to infer + * @return The file's {@link OutputType}. Never {@code null}. + */ + public static OutputType determineOutputTypeFromFile(final File file) { + return determineOutputTypeFromFile(file.toPath()); + } + + /** + * Attempts to determine the type of file/data to write based on the File path being + * written to. Will attempt to determine using the logical filename; if that fails it will + * attempt to resolve any symlinks and try again. If that fails, and the output file exists + * but is neither a file or directory then VCF_STREAM is returned. + * + * @param path A file whose {@link OutputType} we want to infer + * @return The file's {@link OutputType}. Never {@code null}. */ - protected static OutputType determineOutputTypeFromFile(final File f) { - if (isBCF(f)) { + public static OutputType determineOutputTypeFromFile(final Path path) { + if (isBCF(path)) { return OutputType.BCF; - } else if (isCompressedVCF(f)) { + } else if (isCompressedVCF(path)) { return OutputType.BLOCK_COMPRESSED_VCF; - } else if (isVCF(f)) { + } else if (isVCF(path)) { return OutputType.VCF; } else { // See if we have a special file (device, named pipe, etc.) - final File canonical = new File(IOUtil.getFullCanonicalPath(f)); - if (!canonical.equals(f)) { - return determineOutputTypeFromFile(canonical); + try { + final Path canonicalPath = path.toRealPath(); + if (!canonicalPath.equals(path)) { + return determineOutputTypeFromFile(canonicalPath); + } + } catch (java.nio.file.NoSuchFileException nsf) { + // toRealPath failed because the "real" file couldn't be found. + // We do nothing, just continue with the original path. + } catch (IOException x) { + throw new RuntimeIOException(x); } - else if (f.exists() && !f.isFile() && !f.isDirectory()) { + if (Files.exists(path) && !Files.isRegularFile(path) && !Files.isDirectory(path)) { return OutputType.VCF_STREAM; } else { return OutputType.UNSPECIFIED; @@ -490,31 +546,31 @@ else if (f.exists() && !f.isFile() && !f.isDirectory()) { } } - private static boolean isVCF(final File outFile) { - return outFile != null && outFile.getName().endsWith(IOUtil.VCF_FILE_EXTENSION); + private static boolean isVCF(final Path outPath) { + return outPath != null && outPath.getFileName().toString().endsWith(IOUtil.VCF_FILE_EXTENSION); } - private static boolean isBCF(final File outFile) { - return outFile != null && outFile.getName().endsWith(IOUtil.BCF_FILE_EXTENSION); + private static boolean isBCF(final Path outPath) { + return outPath != null && outPath.getFileName().toString().endsWith(IOUtil.BCF_FILE_EXTENSION); } - private static boolean isCompressedVCF(final File outFile) { - if (outFile == null) + private static boolean isCompressedVCF(final Path outPath) { + if (outPath == null) return false; - return AbstractFeatureReader.hasBlockCompressedExtension(outFile); + return IOUtil.hasBlockCompressedExtension(outPath); } - private VariantContextWriter createVCFWriter(final File writerFile, final OutputStream writerStream) { + private VariantContextWriter createVCFWriter(final Path writerPath, final OutputStream writerStream) { if (idxCreator == null) { - return new VCFWriter(writerFile, writerStream, refDict, + return new VCFWriter(writerPath, writerStream, refDict, options.contains(Options.INDEX_ON_THE_FLY), options.contains(Options.DO_NOT_WRITE_GENOTYPES), options.contains(Options.ALLOW_MISSING_FIELDS_IN_HEADER), options.contains(Options.WRITE_FULL_FORMAT_FIELD)); } else { - return new VCFWriter(writerFile, writerStream, refDict, idxCreator, + return new VCFWriter(writerPath, writerStream, refDict, idxCreator, options.contains(Options.INDEX_ON_THE_FLY), options.contains(Options.DO_NOT_WRITE_GENOTYPES), options.contains(Options.ALLOW_MISSING_FIELDS_IN_HEADER), @@ -522,14 +578,14 @@ private VariantContextWriter createVCFWriter(final File writerFile, final Output } } - private VariantContextWriter createBCFWriter(final File writerFile, final OutputStream writerStream) { + private VariantContextWriter createBCFWriter(final Path writerPath, final OutputStream writerStream) { if (idxCreator == null) { - return new BCF2Writer(writerFile, writerStream, refDict, + return new BCF2Writer(writerPath, writerStream, refDict, options.contains(Options.INDEX_ON_THE_FLY), options.contains(Options.DO_NOT_WRITE_GENOTYPES)); } else { - return new BCF2Writer(writerFile, writerStream, refDict, idxCreator, + return new BCF2Writer(writerPath, writerStream, refDict, idxCreator, options.contains(Options.INDEX_ON_THE_FLY), options.contains(Options.DO_NOT_WRITE_GENOTYPES)); } diff --git a/src/main/java/htsjdk/variant/vcf/AbstractVCFCodec.java b/src/main/java/htsjdk/variant/vcf/AbstractVCFCodec.java index 8a55a19462..dcb4352c95 100644 --- a/src/main/java/htsjdk/variant/vcf/AbstractVCFCodec.java +++ b/src/main/java/htsjdk/variant/vcf/AbstractVCFCodec.java @@ -228,7 +228,22 @@ protected VCFHeader parseHeaderFromLines( final List headerStrings, fina return this.header; } - /** + /** + * @return the header that was either explicitly set on this codec, or read from the file. May be null. + * The returned value should not be modified. + */ + public VCFHeader getHeader() { + return header; + } + + /** + * @return the version number that was either explicitly set on this codec, or read from the file. May be null. + */ + public VCFHeaderVersion getVersion() { + return version; + } + + /** * Explicitly set the VCFHeader on this codec. This will overwrite the header read from the file * and the version state stored in this instance; conversely, reading the header from a file will * overwrite whatever is set here. The returned header may not be identical to the header argument @@ -680,6 +695,7 @@ public LazyGenotypesContext.LazyData createGenotypeMap(final String str, alleleMap.clear(); // cycle through the genotype strings + boolean PlIsSet = false; for (int genotypeOffset = 1; genotypeOffset < nParts; genotypeOffset++) { List genotypeValues = ParsingUtils.split(genotypeParts[genotypeOffset], VCFConstants.GENOTYPE_FIELD_SEPARATOR_CHAR); @@ -718,8 +734,12 @@ public LazyGenotypesContext.LazyData createGenotypeMap(final String str, gb.AD(decodeInts(genotypeValues.get(i))); } else if (gtKey.equals(VCFConstants.GENOTYPE_PL_KEY)) { gb.PL(decodeInts(genotypeValues.get(i))); + PlIsSet = true; } else if (gtKey.equals(VCFConstants.GENOTYPE_LIKELIHOODS_KEY)) { - gb.PL(GenotypeLikelihoods.fromGLField(genotypeValues.get(i)).getAsPLs()); + // Do not overwrite PL with data from GL + if (!PlIsSet) { + gb.PL(GenotypeLikelihoods.fromGLField(genotypeValues.get(i)).getAsPLs()); + } } else if (gtKey.equals(VCFConstants.DEPTH_KEY)) { gb.DP(Integer.valueOf(genotypeValues.get(i))); } else { diff --git a/src/main/java/htsjdk/variant/vcf/VCFCompoundHeaderLine.java b/src/main/java/htsjdk/variant/vcf/VCFCompoundHeaderLine.java index 4d8c3447fc..481ca924a2 100644 --- a/src/main/java/htsjdk/variant/vcf/VCFCompoundHeaderLine.java +++ b/src/main/java/htsjdk/variant/vcf/VCFCompoundHeaderLine.java @@ -202,9 +202,12 @@ protected VCFCompoundHeaderLine(String line, VCFHeaderVersion version, Supported } private void validate() { + if (type != VCFHeaderLineType.Flag && countType == VCFHeaderLineCount.INTEGER && count <= 0) + throw new IllegalArgumentException(String.format("Invalid count number, with fixed count the number should be 1 or higher: key=%s name=%s type=%s desc=%s lineType=%s count=%s", + getKey(), name, type, description, lineType, count)); if (name == null || type == null || description == null || lineType == null) throw new IllegalArgumentException(String.format("Invalid VCFCompoundHeaderLine: key=%s name=%s type=%s desc=%s lineType=%s", - super.getKey(), name, type, description, lineType)); + getKey(), name, type, description, lineType)); if (name.contains("<") || name.contains(">")) throw new IllegalArgumentException("VCFHeaderLine: ID cannot contain angle brackets"); if (name.contains("=")) diff --git a/src/main/java/htsjdk/variant/vcf/VCFEncoder.java b/src/main/java/htsjdk/variant/vcf/VCFEncoder.java index 0605b73b9f..96dd104ae9 100644 --- a/src/main/java/htsjdk/variant/vcf/VCFEncoder.java +++ b/src/main/java/htsjdk/variant/vcf/VCFEncoder.java @@ -1,5 +1,6 @@ package htsjdk.variant.vcf; +import htsjdk.samtools.util.RuntimeIOException; import htsjdk.tribble.util.ParsingUtils; import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.Genotype; @@ -9,6 +10,7 @@ import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.variantcontext.writer.IntGenotypeFieldAccessors; +import java.io.IOException; import java.lang.reflect.Array; import java.nio.charset.Charset; import java.util.ArrayList; @@ -64,15 +66,42 @@ public void setAllowMissingFieldsInHeader(final boolean allow) { this.allowMissingFieldsInHeader = allow; } + /** + * encodes a {@link VariantContext} as a VCF line + * + * Depending on the use case it may be more efficient to {@link #write(Appendable, VariantContext)} directly + * instead of creating an intermediate string. + * + * @return the VCF line + */ public String encode(final VariantContext context) { - if (this.header == null) { - throw new NullPointerException("The header field must be set on the VCFEncoder before encoding records."); + try { + final StringBuilder stringBuilder = new StringBuilder(1000); + write(stringBuilder, context); + return stringBuilder.toString(); + } catch (final IOException error) { + throw new RuntimeIOException("Cannot encode variant", error); } + } - final StringBuilder stringBuilder = new StringBuilder(); + /** + * encodes a {@link VariantContext} context as VCF, and writes it directly to an {@link Appendable} + * + * This may be more efficient than calling {@link #encode(VariantContext)} and then writing the result since it + * avoids creating an intermediate string. + * + * @param vcfOutput the {@link Appendable} to write to + * @param context the variant + * @return the java.lang.Appendable 'vcfOutput' + * @throws IOException + */ + public void write(final Appendable vcfOutput, final VariantContext context) throws IOException { + if (this.header == null) { + throw new NullPointerException("The header field must be set on the VCFEncoder before encoding records."); + } // CHROM - stringBuilder.append(context.getContig()).append(VCFConstants.FIELD_SEPARATOR) + vcfOutput.append(context.getContig()).append(VCFConstants.FIELD_SEPARATOR) // POS .append(String.valueOf(context.getStart())).append(VCFConstants.FIELD_SEPARATOR) // ID @@ -81,27 +110,27 @@ public String encode(final VariantContext context) { .append(context.getReference().getDisplayString()).append(VCFConstants.FIELD_SEPARATOR); // ALT - if (context.isVariant()) { + if ( context.isVariant() ) { Allele altAllele = context.getAlternateAllele(0); String alt = altAllele.getDisplayString(); - stringBuilder.append(alt); + vcfOutput.append(alt); for (int i = 1; i < context.getAlternateAlleles().size(); i++) { altAllele = context.getAlternateAllele(i); alt = altAllele.getDisplayString(); - stringBuilder.append(','); - stringBuilder.append(alt); + vcfOutput.append(','); + vcfOutput.append(alt); } } else { - stringBuilder.append(VCFConstants.EMPTY_ALTERNATE_ALLELE_FIELD); + vcfOutput.append(VCFConstants.EMPTY_ALTERNATE_ALLELE_FIELD); } - stringBuilder.append(VCFConstants.FIELD_SEPARATOR); + vcfOutput.append(VCFConstants.FIELD_SEPARATOR); // QUAL - if (!context.hasLog10PError()) stringBuilder.append(VCFConstants.MISSING_VALUE_v4); - else stringBuilder.append(formatQualValue(context.getPhredScaledQual())); - stringBuilder.append(VCFConstants.FIELD_SEPARATOR) + if ( ! context.hasLog10PError()) vcfOutput.append(VCFConstants.MISSING_VALUE_v4); + else vcfOutput.append(formatQualValue(context.getPhredScaledQual())); + vcfOutput.append(VCFConstants.FIELD_SEPARATOR) // FILTER .append(getFilterString(context)).append(VCFConstants.FIELD_SEPARATOR); @@ -114,31 +143,31 @@ public String encode(final VariantContext context) { final String outputValue = formatVCFField(field.getValue()); if (outputValue != null) infoFields.put(field.getKey(), outputValue); } - writeInfoString(infoFields, stringBuilder); + writeInfoString(infoFields, vcfOutput); // FORMAT final GenotypesContext gc = context.getGenotypes(); if (gc.isLazyWithData() && ((LazyGenotypesContext) gc).getUnparsedGenotypeData() instanceof String) { - stringBuilder.append(VCFConstants.FIELD_SEPARATOR); - stringBuilder.append(((LazyGenotypesContext) gc).getUnparsedGenotypeData().toString()); + vcfOutput.append(VCFConstants.FIELD_SEPARATOR); + vcfOutput.append(((LazyGenotypesContext) gc).getUnparsedGenotypeData().toString()); } else { final List genotypeAttributeKeys = context.calcVCFGenotypeKeys(this.header); - if (!genotypeAttributeKeys.isEmpty()) { + if ( ! genotypeAttributeKeys.isEmpty()) { for (final String format : genotypeAttributeKeys) - if (!this.header.hasFormatLine(format)) + if ( ! this.header.hasFormatLine(format)) fieldIsMissingFromHeaderError(context, format, "FORMAT"); final String genotypeFormatString = ParsingUtils.join(VCFConstants.GENOTYPE_FIELD_SEPARATOR, genotypeAttributeKeys); - stringBuilder.append(VCFConstants.FIELD_SEPARATOR); - stringBuilder.append(genotypeFormatString); + vcfOutput.append(VCFConstants.FIELD_SEPARATOR); + vcfOutput.append(genotypeFormatString); final Map alleleStrings = buildAlleleStrings(context); - addGenotypeData(context, alleleStrings, genotypeAttributeKeys, stringBuilder); + appendGenotypeData(context, alleleStrings, genotypeAttributeKeys, vcfOutput); } } - return stringBuilder.toString(); + } VCFHeader getVCFHeader() { @@ -160,7 +189,7 @@ private String getFilterString(final VariantContext vc) { else return VCFConstants.UNFILTERED; } - private String formatQualValue(final double qual) { + private static String formatQualValue(final double qual) { String s = String.format(QUAL_FORMAT_STRING, qual); if (s.endsWith(QUAL_FORMAT_EXTENSION_TO_TRIM)) s = s.substring(0, s.length() - QUAL_FORMAT_EXTENSION_TO_TRIM.length()); @@ -170,27 +199,28 @@ private String formatQualValue(final double qual) { private void fieldIsMissingFromHeaderError(final VariantContext vc, final String id, final String field) { if (!allowMissingFieldsInHeader) throw new IllegalStateException("Key " + id + " found in VariantContext field " + field - + " at " + vc.getContig() + ":" + vc.getStart() - + " but this key isn't defined in the VCFHeader. We require all VCFs to have" - + " complete VCF headers by default."); + + " at " + vc.getContig() + ":" + vc.getStart() + + " but this key isn't defined in the VCFHeader. We require all VCFs to have" + + " complete VCF headers by default."); } + @SuppressWarnings("rawtypes") String formatVCFField(final Object val) { final String result; - if (val == null) + if ( val == null ) result = VCFConstants.MISSING_VALUE_v4; - else if (val instanceof Double) + else if ( val instanceof Double ) result = formatVCFDouble((Double) val); - else if (val instanceof Boolean) - result = (Boolean) val ? "" : null; // empty string for true, null for false - else if (val instanceof List) { - result = formatVCFField(((List) val).toArray()); - } else if (val.getClass().isArray()) { + else if ( val instanceof Boolean ) + result = (Boolean)val ? "" : null; // empty string for true, null for false + else if ( val instanceof List ) { + result = formatVCFField(((List)val).toArray()); + } else if ( val.getClass().isArray() ) { final int length = Array.getLength(val); - if (length == 0) + if ( length == 0 ) return formatVCFField(null); final StringBuilder sb = new StringBuilder(formatVCFField(Array.get(val, 0))); - for (int i = 1; i < length; i++) { + for ( int i = 1; i < length; i++) { sb.append(','); sb.append(formatVCFField(Array.get(val, i))); } @@ -248,25 +278,40 @@ static boolean isMissingValue(final String s) { * Add the genotype data */ public void addGenotypeData(final VariantContext vc, final Map alleleMap, final List genotypeFormatKeys, final StringBuilder builder) { - final int ploidy = vc.getMaxPloidy(2); + try { + appendGenotypeData(vc,alleleMap,genotypeFormatKeys,builder); + } catch (final IOException err) { + throw new RuntimeIOException("addGenotypeData failed",err); + } + } + + /** + * Add the genotype Data to a java.lang.Appendable + * @param vc the variant + * @param alleleMap + * @param genotypeFormatKeys + * @param vcfoutput VCF output + * @throws IOException + */ + private void appendGenotypeData(final VariantContext vc, final Map alleleMap, final List genotypeFormatKeys, final Appendable vcfoutput) throws IOException {final int ploidy = vc.getMaxPloidy(2); for (final String sample : this.header.getGenotypeSamples()) { - builder.append(VCFConstants.FIELD_SEPARATOR); + vcfoutput.append(VCFConstants.FIELD_SEPARATOR); Genotype g = vc.getGenotype(sample); if (g == null) g = GenotypeBuilder.createMissing(sample, ploidy); - final List attrs = new ArrayList(genotypeFormatKeys.size()); + final List attrs = new ArrayList<>(genotypeFormatKeys.size()); for (final String field : genotypeFormatKeys) { if (field.equals(VCFConstants.GENOTYPE_KEY)) { if (!g.isAvailable()) { throw new IllegalStateException("GTs cannot be missing for some samples if they are available for others in the record"); } - writeAllele(g.getAllele(0), alleleMap, builder); + writeAllele(g.getAllele(0), alleleMap, vcfoutput); for (int i = 1; i < g.getPloidy(); i++) { - builder.append(g.isPhased() ? VCFConstants.PHASED : VCFConstants.UNPHASED); - writeAllele(g.getAllele(i), alleleMap, builder); + vcfoutput.append(g.isPhased() ? VCFConstants.PHASED : VCFConstants.UNPHASED); + writeAllele(g.getAllele(i), alleleMap, vcfoutput); } continue; @@ -328,10 +373,10 @@ else if (intValues.length == 1) // fast path } for (int i = 0; i < attrs.size(); i++) { - if (i > 0 || genotypeFormatKeys.contains(VCFConstants.GENOTYPE_KEY)) { - builder.append(VCFConstants.GENOTYPE_FIELD_SEPARATOR); + if ( i > 0 || genotypeFormatKeys.contains(VCFConstants.GENOTYPE_KEY)) { + vcfoutput.append(VCFConstants.GENOTYPE_FIELD_SEPARATOR); } - builder.append(attrs.get(i)); + vcfoutput.append(attrs.get(i)); } } } @@ -339,24 +384,24 @@ else if (intValues.length == 1) // fast path /* * Create the info string; assumes that no values are null */ - private void writeInfoString(final Map infoFields, final StringBuilder builder) { - if (infoFields.isEmpty()) { - builder.append(VCFConstants.EMPTY_INFO_FIELD); + private void writeInfoString(final Map infoFields, final Appendable vcfoutput) throws IOException { + if ( infoFields.isEmpty() ) { + vcfoutput.append(VCFConstants.EMPTY_INFO_FIELD); return; } boolean isFirst = true; for (final Map.Entry entry : infoFields.entrySet()) { if (isFirst) isFirst = false; - else builder.append(VCFConstants.INFO_FIELD_SEPARATOR); + else vcfoutput.append(VCFConstants.INFO_FIELD_SEPARATOR); - builder.append(entry.getKey()); + vcfoutput.append(entry.getKey()); - if (!entry.getValue().equals("")) { + if ( ! entry.getValue().isEmpty()) { final VCFInfoHeaderLine metaData = this.header.getInfoHeaderLine(entry.getKey()); - if (metaData == null || metaData.getCountType() != VCFHeaderLineCount.INTEGER || metaData.getCount() != 0) { - builder.append('='); - builder.append(entry.getValue()); + if ( metaData == null || metaData.getCountType() != VCFHeaderLineCount.INTEGER || metaData.getCount() != 0 ) { + vcfoutput.append('='); + vcfoutput.append(entry.getValue()); } } } @@ -374,10 +419,11 @@ public Map buildAlleleStrings(final VariantContext vc) { return alleleMap; } - private void writeAllele(final Allele allele, final Map alleleMap, final StringBuilder builder) { + private static void writeAllele(final Allele allele, final Map alleleMap, final Appendable vcfOutput) throws IOException { final String encoding = alleleMap.get(allele); - if (encoding == null) + if (encoding == null) { throw new RuntimeException("Allele " + allele + " is not an allele in the variant context"); - builder.append(encoding); + } + vcfOutput.append(encoding); } } diff --git a/src/main/java/htsjdk/variant/vcf/VCFFileReader.java b/src/main/java/htsjdk/variant/vcf/VCFFileReader.java index 64b66da4f3..da61822890 100644 --- a/src/main/java/htsjdk/variant/vcf/VCFFileReader.java +++ b/src/main/java/htsjdk/variant/vcf/VCFFileReader.java @@ -1,3 +1,27 @@ +/* + * The MIT License + * + * Copyright (c) 2013 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.variant.vcf; import htsjdk.samtools.SAMFileHeader; @@ -92,8 +116,7 @@ public VCFFileReader(final File file, final File indexFile, final boolean requir * Returns the SAMSequenceDictionary from the provided VCF file. */ public static SAMSequenceDictionary getSequenceDictionary(final Path path) { - final SAMSequenceDictionary dict = new VCFFileReader(path, false).getFileHeader().getSequenceDictionary(); - return dict; + return new VCFFileReader(path, false).getFileHeader().getSequenceDictionary(); } /** @@ -135,7 +158,7 @@ public VCFFileReader(final Path path, final Path indexPath, final boolean requir * Parse a VCF file and convert to an IntervalList The name field of the IntervalList is taken from the ID field of the variant, if it exists. if not, * creates a name of the format interval-n where n is a running number that increments only on un-named intervals * - * @param path + * @param path a VCF * @return */ public static IntervalList toIntervalList(final Path path) { @@ -152,9 +175,12 @@ public static IntervalList toIntervalList(final Path path, final boolean include * Parse a VCF file and convert to an IntervalList The name field of the IntervalList is taken from the ID field of the variant, if it exists. if not, * creates a name of the format interval-n where n is a running number that increments only on un-named intervals * - * @param file - * @return + * @param file a VCF + * @return an {@link IntervalList} + * + * @deprecated since July 2018 use {@link #toIntervalList(Path)} instead */ + @Deprecated public static IntervalList fromVcf(final File file) { return toIntervalList(file.toPath()); } @@ -165,15 +191,18 @@ public static IntervalList fromVcf(final File file) { * * @param file * @return + * @deprecated since July 2018 use {@link #toIntervalList(Path, boolean)} instead */ + @Deprecated public static IntervalList fromVcf(final File file, final boolean includeFiltered) { return toIntervalList(file.toPath(), includeFiltered); } /** - * Converts a vcf to an IntervalList. The name field of the IntervalList is taken from the ID field of the variant, if it exists. If not, - * creates a name of the format interval-n where n is a running number that increments only on un-named intervals - * Will use a "END" tag in the info field as the end of the interval (if exists). + * Converts the underlying VCFFileReader to an IntervalList. The name field of the IntervalList is taken from the + * ID field of the variant, if it exists. If not, creates a name of the format 'interval-n' where n is a running + * number that increments on un-named intervals. Will use the "END" tag in the INFO field as the end of the interval + * (if exists). * * @return an IntervalList constructed from input vcf */ @@ -182,49 +211,64 @@ public IntervalList toIntervalList() { } public IntervalList toIntervalList(final boolean includeFiltered) { - - //grab the dictionary from the VCF and use it in the IntervalList - final SAMSequenceDictionary dict = getFileHeader().getSequenceDictionary(); - final SAMFileHeader samFileHeader = new SAMFileHeader(); - samFileHeader.setSequenceDictionary(dict); - final IntervalList list = new IntervalList(samFileHeader); - - int intervals = 0; - for (final VariantContext vc : this) { - if (includeFiltered || !vc.isFiltered()) { - String name = vc.getID(); - final Integer intervalEnd = vc.getCommonInfo().getAttributeAsInt("END", vc.getEnd()); - if (".".equals(name) || name == null) - name = "interval-" + (++intervals); - list.add(new Interval(vc.getContig(), vc.getStart(), intervalEnd, false, name)); - } - } - - return list; + return toIntervalList(this, includeFiltered); } /** * Converts a vcf to an IntervalList. The name field of the IntervalList is taken from the ID field of the variant, if it exists. If not, - * creates a name of the format interval-n where n is a running number that increments only on un-named intervals - * Will use a "END" tag in the info field as the end of the interval (if exists). + * creates a name of the format interval-n where n is a running number that increments only on un-named intervals. + * Will use a "END" tag in the INFO field as the end of the interval (if exists). * * @param vcf the vcfReader to be used for the conversion * @return an IntervalList constructed from input vcf + * + * @deprecated since July 2018 since use {@link #toIntervalList(VCFFileReader)} instead */ + @Deprecated public static IntervalList fromVcf(final VCFFileReader vcf) { return fromVcf(vcf, false); } /** * Converts a vcf to an IntervalList. The name field of the IntervalList is taken from the ID field of the variant, if it exists. If not, - * creates a name of the format interval-n where n is a running number that increments only on un-named intervals - * Will use a "END" tag in the info field as the end of the interval (if exists). + * creates a name of the format interval-n where n is a running number that increments only on un-named intervals. + * Will use a "END" tag in the INFO field as the end of the interval (if exists). * * @param vcf the vcfReader to be used for the conversion * @return an IntervalList constructed from input vcf */ + public static IntervalList toIntervalList(final VCFFileReader vcf) { + return toIntervalList(vcf, false); + } + + + /** + * Converts a vcf to an IntervalList. The name field of the IntervalList is taken from the ID field of the variant, if it exists. If not, + * creates a name of the format interval-n where n is a running number that increments only on un-named intervals. + * Will use a "END" tag in the INFO field as the end of the interval (if exists). + * + * @param vcf the vcfReader to be used for the conversion + * @return an IntervalList constructed from input vcf + * + * @deprecated since July 2018 since use {@link #toIntervalList(VCFFileReader, boolean)} instead + */ + @Deprecated public static IntervalList fromVcf(final VCFFileReader vcf, final boolean includeFiltered) { + + return toIntervalList(vcf, includeFiltered); + } + + /** + * Converts a {@link VCFFileReader} to an IntervalList. The name field of the IntervalList is taken from the ID field + * of the variant, if it exists. If not, creates a name of the format interval-n where n is a running number that increments + * only on un-named intervals. Will use a "END" tag in the INFO field as the end of the interval (if exists). + * + * @param vcf the vcfReader to be used for the conversion + * @return an IntervalList constructed from input vcf + */ + public static IntervalList toIntervalList(final VCFFileReader vcf, final boolean includeFiltered) { + //grab the dictionary from the VCF and use it in the IntervalList final SAMSequenceDictionary dict = vcf.getFileHeader().getSequenceDictionary(); final SAMFileHeader samFileHeader = new SAMFileHeader(); @@ -235,8 +279,8 @@ public static IntervalList fromVcf(final VCFFileReader vcf, final boolean includ for (final VariantContext vc : vcf) { if (includeFiltered || !vc.isFiltered()) { String name = vc.getID(); - final Integer intervalEnd = vc.getCommonInfo().getAttributeAsInt("END", vc.getEnd()); - if (".".equals(name) || name == null) + final Integer intervalEnd = vc.getCommonInfo().getAttributeAsInt(VCFConstants.END_KEY, vc.getEnd()); + if (VCFConstants.EMPTY_ID_FIELD.equals(name) || name == null) name = "interval-" + (++intervals); list.add(new Interval(vc.getContig(), vc.getStart(), intervalEnd, false, name)); } @@ -281,6 +325,16 @@ public CloseableIterator query(final String chrom, final int sta } } + /** + * Queries for records overlapping the {@link Locatable} specified. + * Note that this method requires VCF files with an associated index. If no index exists a TribbleException will be thrown. + * + * @return non-null iterator over VariantContexts + */ + public CloseableIterator query(final Locatable locatable) { + return query(locatable.getContig(), locatable.getStart(), locatable.getEnd()); + } + @Override public void close() { try { diff --git a/src/main/java/htsjdk/variant/vcf/VCFHeader.java b/src/main/java/htsjdk/variant/vcf/VCFHeader.java index 00ed26ee04..c5cab7434b 100644 --- a/src/main/java/htsjdk/variant/vcf/VCFHeader.java +++ b/src/main/java/htsjdk/variant/vcf/VCFHeader.java @@ -246,16 +246,16 @@ public List getFilterLines() { } /** - * @return all of the VCF FILTER lines in their original file order, or an empty list if none were present + * @return all of the VCF ID-based header lines in their original file order, or an empty list if none were present */ public List getIDHeaderLines() { - final List filters = new ArrayList(); + final List lines = new ArrayList(); for (final VCFHeaderLine line : mMetaData) { if (line instanceof VCFIDHeaderLine) { - filters.add((VCFIDHeaderLine)line); + lines.add((VCFIDHeaderLine)line); } } - return filters; + return lines; } /** diff --git a/src/main/java/htsjdk/variant/vcf/VCFStandardHeaderLines.java b/src/main/java/htsjdk/variant/vcf/VCFStandardHeaderLines.java index de2817c96b..035cdd3c39 100644 --- a/src/main/java/htsjdk/variant/vcf/VCFStandardHeaderLines.java +++ b/src/main/java/htsjdk/variant/vcf/VCFStandardHeaderLines.java @@ -158,6 +158,7 @@ private static void registerStandard(final VCFFormatHeaderLine line) { registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_PL_KEY, VCFHeaderLineCount.G, VCFHeaderLineType.Integer, "Normalized, Phred-scaled likelihoods for genotypes as defined in the VCF specification")); registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_ALLELE_DEPTHS, VCFHeaderLineCount.R, VCFHeaderLineType.Integer, "Allelic depths for the ref and alt alleles in the order listed")); registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_FILTER_KEY, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Genotype-level filter")); + registerStandard(new VCFFormatHeaderLine(VCFConstants.PHASE_SET_KEY, 1, VCFHeaderLineType.Integer, "Phasing set (typically the position of the first variant in the set)")); registerStandard(new VCFFormatHeaderLine(VCFConstants.PHASE_QUALITY_KEY, 1, VCFHeaderLineType.Float, "Read-backed phasing quality")); // INFO lines diff --git a/src/test/java/htsjdk/cram/io/ExternalCompressionTest.java b/src/test/java/htsjdk/cram/io/ExternalCompressionTest.java deleted file mode 100644 index 60a65197de..0000000000 --- a/src/test/java/htsjdk/cram/io/ExternalCompressionTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package htsjdk.cram.io; - -import htsjdk.HtsjdkTest; -import htsjdk.samtools.cram.io.ExternalCompression; -import org.testng.Assert; -import org.testng.annotations.Test; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -public class ExternalCompressionTest extends HtsjdkTest { - public static final File BZIP2_FILE = new File("src/test/resources/htsjdk/samtools/cram/io/bzip2-test.bz2"); - public static final byte [] TEST_BYTES = "This is a simple string to test BZip2".getBytes(); - - @Test - public void testBZip2Decompression() throws IOException { - final byte [] input = Files.readAllBytes(BZIP2_FILE.toPath()); - final byte [] output = ExternalCompression.unbzip2(input); - Assert.assertEquals(output, "BZip2 worked".getBytes()); - } - - @Test - public void testBZip2Roundtrip() throws IOException { - final byte [] compressed = ExternalCompression.bzip2(TEST_BYTES); - final byte [] restored = ExternalCompression.unbzip2(compressed); - Assert.assertEquals(TEST_BYTES, restored); - } -} diff --git a/src/test/java/htsjdk/samtools/BAMCigarOverflowTest.java b/src/test/java/htsjdk/samtools/BAMCigarOverflowTest.java index 8f91c64485..5f8f3b24f3 100644 --- a/src/test/java/htsjdk/samtools/BAMCigarOverflowTest.java +++ b/src/test/java/htsjdk/samtools/BAMCigarOverflowTest.java @@ -26,5 +26,4 @@ public void testCigarOverflow() throws Exception { //Cast to int to avoid an ambiguity in the assertEquals() call between assertEquals(int,int) and assertEquals(Object,Object). assertEquals(testBAMRecord.computeIndexingBin(), (int) testBAMRecord.getIndexingBin()); } - } diff --git a/src/test/java/htsjdk/samtools/BAMFileWriterTest.java b/src/test/java/htsjdk/samtools/BAMFileWriterTest.java index 3bb46e6f77..ab6daa8c99 100644 --- a/src/test/java/htsjdk/samtools/BAMFileWriterTest.java +++ b/src/test/java/htsjdk/samtools/BAMFileWriterTest.java @@ -24,17 +24,18 @@ package htsjdk.samtools; import htsjdk.HtsjdkTest; +import htsjdk.samtools.metrics.MetricsFile; +import htsjdk.samtools.util.BinaryCodec; +import htsjdk.samtools.util.BlockCompressedInputStream; import htsjdk.samtools.util.CloseableIterator; -import htsjdk.samtools.util.CloserUtil; import htsjdk.samtools.util.SequenceUtil; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; +import java.io.*; +import java.util.ArrayList; +import java.util.List; /** * Test that BAM writing doesn't blow up. For presorted writing, the resulting BAM file is read and contents are @@ -60,50 +61,69 @@ private SAMRecordSetBuilder getRecordSetBuilder(final boolean sortForMe, final S * @param presorted If true, samText is in the order specified by sortOrder */ private void testHelper(final SAMRecordSetBuilder samRecordSetBuilder, final SAMFileHeader.SortOrder sortOrder, final boolean presorted) throws Exception { - final SamReader samReader = samRecordSetBuilder.getSamReader(); final File bamFile = File.createTempFile("test.", BamFileIoUtils.BAM_FILE_EXTENSION); bamFile.deleteOnExit(); - samReader.getFileHeader().setSortOrder(sortOrder); - final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeSAMOrBAMWriter(samReader.getFileHeader(), presorted, bamFile); - CloseableIterator it = samReader.iterator(); - while (it.hasNext()) { - bamWriter.addAlignment(it.next()); - } - bamWriter.close(); - it.close(); - samReader.close(); + try (final SamReader samReader = samRecordSetBuilder.getSamReader()) { + samReader.getFileHeader().setSortOrder(sortOrder); + try (final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeSAMOrBAMWriter(samReader.getFileHeader(), presorted, bamFile); + final CloseableIterator it = samReader.iterator()) { + while (it.hasNext()) { + bamWriter.addAlignment(it.next()); + } + } + } if (presorted) { // If SAM text input was presorted, then we can compare SAM object to BAM object verifyBAMFile(samRecordSetBuilder, bamFile); } + + final File tempMetrics = File.createTempFile("CGTagTest", ".validation_metrics"); + try ( + final SamReader samReader = SamReaderFactory.makeDefault().open(bamFile); + final OutputStream outputStream = new FileOutputStream(tempMetrics); + final PrintWriter printWriter = new PrintWriter(outputStream)) { + + new SamFileValidator(printWriter, 100).validateSamFileSummary(samReader, null); + } + + final MetricsFile validationMetrics = new MetricsFile<>(); + validationMetrics.read(new FileReader(tempMetrics)); + + Assert.assertNull(validationMetrics.getHistogram().get("ERROR:CG_TAG_FOUND_IN_ATTRIBUTES")); } - private void verifyBAMFile(final SAMRecordSetBuilder samRecordSetBuilder, final File bamFile) { + private void verifyBAMFile(final SAMRecordSetBuilder samRecordSetBuilder, final File bamFile) throws IOException { + try (final SamReader bamReader = SamReaderFactory.makeDefault().open(bamFile); + final SamReader samReader = samRecordSetBuilder.getSamReader()) { + verifySamReadersEqual(samReader, bamReader); + } + } - final SamReader bamReader = SamReaderFactory.makeDefault().open(bamFile); - final SamReader samReader = samRecordSetBuilder.getSamReader(); - samReader.getFileHeader().setSortOrder(bamReader.getFileHeader().getSortOrder()); - Assert.assertEquals(bamReader.getFileHeader(), samReader.getFileHeader()); - final CloseableIterator it = samReader.iterator(); - final CloseableIterator bamIt = bamReader.iterator(); - while (it.hasNext()) { - Assert.assertTrue(bamIt.hasNext()); - final SAMRecord samRecord = it.next(); - final SAMRecord bamRecord = bamIt.next(); + private void verifySamReadersEqual(final SamReader reader2, final SamReader reader1) { - // SAMRecords don't have this set, so stuff it in there - samRecord.setIndexingBin(bamRecord.getIndexingBin()); + reader2.getFileHeader().setSortOrder(reader1.getFileHeader().getSortOrder()); + Assert.assertEquals(reader1.getFileHeader(), reader2.getFileHeader()); - // Force reference index attributes to be populated - samRecord.getReferenceIndex(); - bamRecord.getReferenceIndex(); - samRecord.getMateReferenceIndex(); - bamRecord.getMateReferenceIndex(); + try (final CloseableIterator samIt1 = reader1.iterator(); + final CloseableIterator samIt2 = reader2.iterator()) { + while (samIt2.hasNext()) { + Assert.assertTrue(samIt1.hasNext()); + final SAMRecord samRecord1 = samIt1.next(); + final SAMRecord samRecord2 = samIt2.next(); - Assert.assertEquals(bamRecord, samRecord); + // SAMRecords don't have this set, so stuff it in there + samRecord2.setIndexingBin(samRecord1.getIndexingBin()); + + // Force reference index attributes to be populated + samRecord1.getReferenceIndex(); + samRecord2.getReferenceIndex(); + samRecord1.getMateReferenceIndex(); + samRecord2.getMateReferenceIndex(); + + Assert.assertEquals(samRecord1, samRecord2); + } + Assert.assertFalse(samIt1.hasNext()); } - Assert.assertFalse(bamIt.hasNext()); - CloserUtil.close(samReader); } @DataProvider(name = "test1") @@ -136,12 +156,11 @@ public void testNullRecordHeaders(final String testName, final SAMRecordSetBuild final File bamFile = File.createTempFile("test.", BamFileIoUtils.BAM_FILE_EXTENSION); bamFile.deleteOnExit(); samHeader.setSortOrder(order); - final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeSAMOrBAMWriter(samHeader, presorted, bamFile); - for (final SAMRecord rec : samRecordSetBuilder.getRecords()) { - bamWriter.addAlignment(rec); + try (final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeSAMOrBAMWriter(samHeader, presorted, bamFile)) { + for (final SAMRecord rec : samRecordSetBuilder.getRecords()) { + bamWriter.addAlignment(rec); + } } - bamWriter.close(); - if (presorted) { verifyBAMFile(samRecordSetBuilder, bamFile); } @@ -174,7 +193,7 @@ public void testRecordsMismatchedHeader() throws Exception { final SAMRecordSetBuilder samRecordSetBuilder = getRecordSetBuilder(true, SAMFileHeader.SortOrder.queryname); - // create a fake header to make sure the records cannot be written using an invalid + // create a fake header to make sure the records cannot be written using an invalid // sequence dictionary and unresolvable references final SAMFileHeader fakeHeader = new SAMFileHeader(); fakeHeader.setSortOrder(SAMFileHeader.SortOrder.queryname); @@ -195,7 +214,6 @@ public void testNegativePresorted() throws Exception { Assert.fail("Exception should be thrown"); } - /** * A test to check that BAM changes read bases according with {@link SequenceUtil#toBamReadBasesInPlace}. */ @@ -219,7 +237,6 @@ public void testBAMReadBases() throws IOException { writer.addAlignment(originalSAMRecord); } - final BAMFileReader reader = new BAMFileReader(new ByteArrayInputStream(baos.toByteArray()), null, true, false, ValidationStringency.SILENT, new DefaultSAMRecordFactory()); final CloseableIterator iterator = reader.getIterator(); iterator.hasNext(); @@ -229,4 +246,318 @@ public void testBAMReadBases() throws IOException { Assert.assertEquals(recordFromBAM.getReadBases(), SequenceUtil.toBamReadBasesInPlace(originalSAMRecord.getReadBases())); } + @Test(dataProvider = "longCigarsData") + public void testClearAttributesDoesntVoidLongCigar(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + + builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + + //encode as BAM into ByteArray + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (final BAMFileWriter writer = new BAMFileWriter(baos, null)) { + writer.setHeader(builder.getHeader()); + builder.getRecords().forEach(writer::addAlignment); + } + + //read from ByteArray + final BAMFileReader reader = new BAMFileReader(new ByteArrayInputStream(baos.toByteArray()), null, false, false, ValidationStringency.SILENT, new DefaultSAMRecordFactory()); + final CloseableIterator iterator = reader.getIterator(); + iterator.hasNext(); + final SAMRecord recordFromBAM = iterator.next(); + + //clear attributes before explicitly accessing cigar or attributes + recordFromBAM.clearAttributes(); + + // see that cigar is unscathed + Assert.assertNotNull(recordFromBAM.getCigar()); + Assert.assertFalse(BAMRecord.isSentinelCigar(recordFromBAM.getCigar(), recordFromBAM.getReadLength())); + } + + @Test(dataProvider = "longCigarsData") + public void testSetCigarRemovesCgTagWhenNoLongerLong(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + final SAMRecord frag1 = builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + + frag1.setCigarString(String.format("%dM", cigar.getReadLength())); + testHelper(builder, SAMFileHeader.SortOrder.coordinate, true); + } + + @Test(dataProvider = "longCigarsData") + public void testSetCigarRemovesCgTagWhenStillLong(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + final SAMRecord frag1 = builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + final List cigarOperatorsForTest = getCigarOperatorsForTest(numOps); + + cigarOperatorsForTest.add(CigarOperator.H); + final Cigar cigar2 = Cigar.fromCigarOperators(cigarOperatorsForTest); + + frag1.setCigar(cigar2); + testHelper(builder, SAMFileHeader.SortOrder.coordinate, true); + } + + @Test(dataProvider = "longCigarsData") + public void testSetCigarStringRemovesCgTagWhenNoLongerLong(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + + final SAMRecord frag1 = builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + + frag1.setCigarString(String.format("%dM", cigar.getReadLength())); + testHelper(builder, SAMFileHeader.SortOrder.coordinate, true); + } + + @Test(dataProvider = "longCigarsData") + public void testSetCigarStringRemovesCgTagWhenStillLong(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + + final SAMRecord frag1 = builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + + final List cigarOperatorsForTest = getCigarOperatorsForTest(numOps); + cigarOperatorsForTest.add(CigarOperator.H); + final Cigar cigar2 = Cigar.fromCigarOperators(cigarOperatorsForTest); + + frag1.setCigarString(cigar2.toString()); + testHelper(builder, SAMFileHeader.SortOrder.coordinate, true); + } + + @Test(dataProvider = "longCigarsData") + public void testBinNotNullWhenLargeCigarIsLoaded(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + + builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + + final File bamFile = File.createTempFile("test.", BamFileIoUtils.BAM_FILE_EXTENSION); + bamFile.deleteOnExit(); + + try (final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeSAMOrBAMWriter(builder.getHeader(), false, bamFile)) { + for (final SAMRecord record : builder.getRecords()) + bamWriter.addAlignment(record); + } + + try (final SamReader reader = SamReaderFactory.makeDefault().validationStringency(ValidationStringency.SILENT).open(bamFile)) { + reader.iterator().forEachRemaining(samRecord -> { + samRecord.getCigar(); + Assert.assertNotNull(samRecord.getIndexingBin()); + }); + } + } + + @DataProvider + public Object[][] longCigarsData() { + return new Object[][]{ + {1}, + {10}, + {100}, + {1_000}, + {10_000}, + {BAMRecord.MAX_CIGAR_OPERATORS - 1}, + {BAMRecord.MAX_CIGAR_OPERATORS}, + {BAMRecord.MAX_CIGAR_OPERATORS + 1}, + {100_000}, + {1_000_000} + }; + } + + private final static CigarOperator[] operatorsToUse = new CigarOperator[]{CigarOperator.M, CigarOperator.D, CigarOperator.M, CigarOperator.I}; + + @Test(dataProvider = "longCigarsData") + public void testLongCigarsOneRead(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + + builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + testHelper(builder, SAMFileHeader.SortOrder.coordinate, true); + } + + @Test(dataProvider = "longCigarsData") + public void testLongCigarsZerolengthRead(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + + final SAMRecord sam = builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + sam.setReadBases(new byte[]{}); + sam.setBaseQualityString(""); + // in htsjdk only secondary alignments are allowed to have read-length zero (doesn't validate otherwise) + sam.setSecondaryAlignment(true); + + testHelper(builder, SAMFileHeader.SortOrder.coordinate, true); + } + + private List getCigarOperatorsForTest(final int numOps) { + final List operators = new ArrayList<>(numOps); + for (int i = 0; i < numOps; i++) { + operators.add(operatorsToUse[i % operatorsToUse.length]); + } + operators.add(CigarOperator.M); + return operators; + } + + @Test(dataProvider = "longCigarsData") + public void testLongCigars(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final Cigar cigar = Cigar.fromCigarOperators(getCigarOperatorsForTest(numOps)); + + builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + builder.addPair("pair1", 0, 1, 100_000, false, false, cigar.toString(), cigar.toString(), true, false, 30); + + testHelper(builder, SAMFileHeader.SortOrder.coordinate, true); + } + + @DataProvider + public Object[][] sentinelCigarData() { + return new Object[][]{ + {1, 0, 1}, + {0, 1, 1}, + {0, 0, 0}, + }; + } + + @Test(dataProvider = "sentinelCigarData", expectedExceptions = IllegalStateException.class) + public void testWrongCGTagCigars(final int readOffset, final int refOffset, final int cigarOpsOffset) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final List operators = getCigarOperatorsForTest(BAMRecord.MAX_CIGAR_OPERATORS + cigarOpsOffset); + final Cigar cigar = Cigar.fromCigarOperators(operators); + final int[] cigarEncoding = BinaryCigarCodec.encode(cigar); + + final Cigar sentinelCigar = BAMRecordCodec.makeSentinelCigar(cigar); + final List sentinelCigarElements = new ArrayList<>(2); + + sentinelCigarElements.add(new CigarElement( + sentinelCigar.getCigarElement(0).getLength() + readOffset, + sentinelCigar.getCigarElement(0).getOperator())); + sentinelCigarElements.add(new CigarElement( + sentinelCigar.getCigarElement(1).getLength() + refOffset, + sentinelCigar.getCigarElement(1).getOperator())); + + final String sentinelCigarString = new Cigar(sentinelCigarElements).toString(); + + builder.addPair("pair1", 0, 1, 100_000, false, false, sentinelCigarString, sentinelCigarString, true, false, 30); + + final SAMRecord frag = builder.addFrag("frag1", 0, 1, false, false, sentinelCigarString, null, 30); + frag.setAttribute(SAMTag.CG.name(), cigarEncoding); + + final List pairOfReads = builder.addPair("pair1", 0, 1, 100_000, false, false, cigar.toString(), cigar.toString(), true, false, 30); + for (final SAMRecord rec : pairOfReads) { + rec.setAttribute(SAMTag.CG.name(), cigarEncoding); + } + + final File bamFile = File.createTempFile("test.", BamFileIoUtils.BAM_FILE_EXTENSION); + bamFile.deleteOnExit(); + + try (final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeSAMOrBAMWriter(builder.getHeader(), false, bamFile)) { + for (final SAMRecord record : builder.getRecords()) + bamWriter.addAlignment(record); + } + + try (final SamReader reader = SamReaderFactory.makeDefault().validationStringency(ValidationStringency.SILENT).open(bamFile)) { + reader.iterator().forEachRemaining(SAMRecord::getCigar); + } + } + + @Test(dataProvider = "longCigarsData") + public void testNoCGTagCigars(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + final List operators = getCigarOperatorsForTest(numOps); + final Cigar cigar = Cigar.fromCigarOperators(operators); + + builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + builder.addPair("pair1", 0, 1, 100_000, false, false, cigar.toString(), cigar.toString(), true, false, 30); + + final File bamFile = File.createTempFile("test.", BamFileIoUtils.BAM_FILE_EXTENSION); + bamFile.deleteOnExit(); + + try (final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeSAMOrBAMWriter(builder.getHeader(), false, bamFile)) { + for (SAMRecord record : builder.getRecords()) + bamWriter.addAlignment(record); + } + + try (final SamReader reader = SamReaderFactory.makeDefault().validationStringency(ValidationStringency.SILENT).open(bamFile)) { + reader.iterator().forEachRemaining(rec -> Assert.assertFalse(rec.hasAttribute(SAMTag.CG.name()))); + } + } + + @Test(dataProvider = "longCigarsData", expectedExceptions = AssertionError.class) + public void testMisplacedCGTag(final int numOps) throws Exception { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + builder.setUseBamFile(false); + + final List operators = getCigarOperatorsForTest(numOps); + final Cigar cigar = Cigar.fromCigarOperators(operators); + + final SAMRecord record = builder.addFrag("frag1", 0, 1, false, false, cigar.toString(), null, 30); + record.setAttribute(SAMTag.CG.name(), "Ceci n'est pas une pipe!"); + + final List pairOfReads = builder.addPair("pair1", 0, 1, 100_000, false, false, cigar.toString(), cigar.toString(), true, false, 30); + for (final SAMRecord rec : pairOfReads) { + rec.setAttribute(SAMTag.CG.name(), "Ceci n'est pas une pipe!"); + } + + testHelper(builder, SAMFileHeader.SortOrder.coordinate, true); + } + + @Test + public void testRealDataLongCigar() throws Exception { + final File samFile = new File("src/test/resources/htsjdk/samtools/BAMCigarOverflowTest/cigar-64k.sam.gz"); + final File bamFile = File.createTempFile("test.", BamFileIoUtils.BAM_FILE_EXTENSION); + bamFile.deleteOnExit(); + + try (final SamReader samReader = SamReaderFactory.make().open(samFile); + final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeSAMOrBAMWriter(samReader.getFileHeader(), true, bamFile); + final CloseableIterator it = samReader.iterator()) { + while (it.hasNext()) { + bamWriter.addAlignment(it.next()); + } + } + try (final SamReader samReader = SamReaderFactory.make().open(samFile); + final SamReader bamReader = SamReaderFactory.make().open(bamFile)) { + + verifySamReadersEqual(samReader, bamReader); + } + } + + @Test + public void setAttributeOnBamRecord() throws IOException { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + + builder.addPair("test", 0, 100, 150, false, false, null, null, true, false, 30); + + //encode as BAM into ByteArray + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (final BAMFileWriter writer = new BAMFileWriter(baos, null)) { + writer.setHeader(builder.getHeader()); + builder.forEach(r -> r.setAttribute("xx", "Testing123")); + builder.forEach(writer::addAlignment); + } + + //read from ByteArray + final BAMFileReader reader = new BAMFileReader(new ByteArrayInputStream(baos.toByteArray()), null, false, false, ValidationStringency.SILENT, new DefaultSAMRecordFactory()); + + for (final SAMRecord rec : (Iterable) reader::getIterator) { + + //clear attribute before explicitly accessing cigar or attributes + rec.setAttribute("xx", null); + Assert.assertNull(rec.getAttribute("xx")); + } + } + + @Test + public void testWriteHeader() throws IOException { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(true, SAMFileHeader.SortOrder.coordinate); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + BAMFileWriter.writeHeader(baos, builder.getHeader()); + baos.close(); + + try (BinaryCodec binaryCodec = new BinaryCodec(new DataInputStream(new BlockCompressedInputStream(new ByteArrayInputStream(baos.toByteArray()))))) { + SAMFileHeader samFileHeader = BAMFileReader.readHeader(binaryCodec, ValidationStringency.STRICT, null); + Assert.assertEquals(samFileHeader, builder.getHeader()); + } + } } + + diff --git a/src/test/java/htsjdk/samtools/CRAMComplianceTest.java b/src/test/java/htsjdk/samtools/CRAMComplianceTest.java index cede96f45e..308234ac32 100644 --- a/src/test/java/htsjdk/samtools/CRAMComplianceTest.java +++ b/src/test/java/htsjdk/samtools/CRAMComplianceTest.java @@ -41,14 +41,19 @@ public Object[][] getPartialVerificationData() { {"c1#noseq"}, // unsigned attributes: https://github.com/samtools/htsjdk/issues/499 {"c1#unknown"}, // unsigned attributes: https://github.com/samtools/htsjdk/issues/499 {"ce#5b"}, // reads with no read bases: https://github.com/samtools/htsjdk/issues/509 + {"ce#1000"}, // SAMRecord mismatch: https://github.com/samtools/htsjdk/issues/1189 {"ce#tag_depadded"},// reads with no read bases: https://github.com/samtools/htsjdk/issues/509 {"ce#tag_padded"}, // reads with no read bases: https://github.com/samtools/htsjdk/issues/509 {"ce#unmap"}, // unmapped reads with non-zero MAPQ value that is not restored // https://github.com/samtools/htsjdk/issues/714 - {"xx#triplet"}, // the version 2.1 variant of this file has a bad insertSize, which is - // probably residual detritus from https://github.com/samtools/htsjdk/issues/364 {"xx#minimal"}, // cigar string "5H0M5H" is restored as "10H" // https://github.com/samtools/htsjdk/issues/713 + {"xx#repeated"}, // SAMRecord mismatch: https://github.com/samtools/htsjdk/issues/1189 + {"xx#tlen"}, // SAMRecord mismatch: https://github.com/samtools/htsjdk/issues/1189 + {"xx#tlen2"}, // SAMRecord mismatch: https://github.com/samtools/htsjdk/issues/1189 + {"xx#triplet"}, // the version 2.1 variant of this file has a bad insertSize, which is + // probably residual detritus from https://github.com/samtools/htsjdk/issues/364 + //{"md#1"}, // fails with "offensive record" errors: https://github.com/samtools/htsjdk/issues/1187 }; } @@ -67,6 +72,7 @@ public Object[][] getFullVerificationData() { {"c1#pad1"}, {"c1#pad2"}, {"c1#pad3"}, + {"c2#pad"}, {"ce#1"}, {"ce#2"}, {"ce#5"}, @@ -392,7 +398,7 @@ private void writeRecordsToPath ( // tests to fail since it can change the order of some unmapped reads - this is allowed // by the spec since the order is arbitrary for unmapped. try (final SAMFileWriter writer = new SAMFileWriterFactory() - .makeWriter(samHeader, true, targetPath, referenceFile)) { + .makeWriter(samHeader, true, targetPath, referenceFile.toPath())) { for (SAMRecord rec : recs) { writer.addAlignment(rec); } diff --git a/src/test/java/htsjdk/samtools/CRAMEdgeCasesTest.java b/src/test/java/htsjdk/samtools/CRAMEdgeCasesTest.java index 4fa9b1a59d..6c6a05f4de 100644 --- a/src/test/java/htsjdk/samtools/CRAMEdgeCasesTest.java +++ b/src/test/java/htsjdk/samtools/CRAMEdgeCasesTest.java @@ -3,19 +3,16 @@ import htsjdk.HtsjdkTest; import htsjdk.samtools.cram.CRAMException; import htsjdk.samtools.cram.ref.ReferenceSource; -import htsjdk.samtools.reference.InMemoryReferenceSequenceFile; -import htsjdk.samtools.seekablestream.SeekableStream; import htsjdk.samtools.util.Log; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; /** @@ -79,22 +76,9 @@ public void testNullsAndBeyondRef() throws IOException { testSingleRecord("AAA".getBytes(), "!!!".getBytes(), "A".getBytes()); } - private void testRecords(Collection records, byte[] ref) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InMemoryReferenceSequenceFile refFile = new InMemoryReferenceSequenceFile(); - refFile.add("chr1", ref); - ReferenceSource source = new ReferenceSource(refFile); - final SAMFileHeader header = records.iterator().next().getHeader(); - CRAMFileWriter cramFileWriter = new CRAMFileWriter(baos, source, header, "whatever"); - - Iterator it = records.iterator(); - while (it.hasNext()) { - SAMRecord record = it.next(); - cramFileWriter.addAlignment(record); - } - cramFileWriter.close(); - - CRAMFileReader cramFileReader = new CRAMFileReader(new ByteArrayInputStream(baos.toByteArray()), (SeekableStream) null, source, ValidationStringency.SILENT); + private static void testRecords(Collection records, byte[] ref) throws IOException { + CRAMFileReader cramFileReader = CRAMTestUtils.writeAndReadFromInMemoryCram(records, ref); + Iterator it; final SAMRecordIterator iterator = cramFileReader.getIterator(); Assert.assertTrue(iterator.hasNext()); @@ -113,16 +97,8 @@ private void testRecords(Collection records, byte[] ref) throws IOExc Assert.assertFalse(iterator.hasNext()); } - private void testSingleRecord(SAMRecord record, byte[] ref) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InMemoryReferenceSequenceFile refFile = new InMemoryReferenceSequenceFile(); - refFile.add("chr1", ref); - ReferenceSource source = new ReferenceSource(refFile); - CRAMFileWriter cramFileWriter = new CRAMFileWriter(baos, source, record.getHeader(), "whatever"); - cramFileWriter.addAlignment(record); - cramFileWriter.close(); - - CRAMFileReader cramFileReader = new CRAMFileReader(new ByteArrayInputStream(baos.toByteArray()), (SeekableStream) null, source, ValidationStringency.SILENT); + private static void testSingleRecord(SAMRecord record, byte[] ref) throws IOException { + CRAMFileReader cramFileReader = CRAMTestUtils.writeAndReadFromInMemoryCram(Collections.singletonList(record), ref); final SAMRecordIterator iterator = cramFileReader.getIterator(); Assert.assertTrue(iterator.hasNext()); SAMRecord s2 = iterator.next(); diff --git a/src/test/java/htsjdk/samtools/CRAMFileCRAIIndexTest.java b/src/test/java/htsjdk/samtools/CRAMFileCRAIIndexTest.java index b919c46191..b9c10334a6 100644 --- a/src/test/java/htsjdk/samtools/CRAMFileCRAIIndexTest.java +++ b/src/test/java/htsjdk/samtools/CRAMFileCRAIIndexTest.java @@ -304,6 +304,29 @@ public void testQueryInterval() throws IOException { reader.close(); } + @Test + public void testQueryIntervalWithFilePointers() throws IOException { + CRAMFileReader reader = new CRAMFileReader( + new ByteArraySeekableStream(cramBytes), + new ByteArraySeekableStream(craiBytes), + source, + ValidationStringency.STRICT); + QueryInterval[] query = new QueryInterval[]{new QueryInterval(0, 1519, 1520), new QueryInterval(1, 470535, 470536)}; + BAMFileSpan fileSpan = BAMFileReader.getFileSpan(query, reader.getIndex()); + final CloseableIterator iterator = reader.createIndexIterator(query, false, fileSpan.toCoordinateArray()); + Assert.assertTrue(iterator.hasNext()); + SAMRecord r1 = iterator.next(); + Assert.assertEquals(r1.getReadName(), "3968040"); + + Assert.assertTrue(iterator.hasNext()); + SAMRecord r2 = iterator.next(); + Assert.assertEquals(r2.getReadName(), "140419"); + + Assert.assertFalse(iterator.hasNext()); + iterator.close(); + reader.close(); + } + @BeforeTest public void prepare() throws IOException { Log.setGlobalLogLevel(Log.LogLevel.ERROR); diff --git a/src/test/java/htsjdk/samtools/CRAMFileReaderTest.java b/src/test/java/htsjdk/samtools/CRAMFileReaderTest.java index da53f170cc..a5999f8daf 100644 --- a/src/test/java/htsjdk/samtools/CRAMFileReaderTest.java +++ b/src/test/java/htsjdk/samtools/CRAMFileReaderTest.java @@ -37,6 +37,7 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; +import java.util.NoSuchElementException; /** * Additional tests for CRAMFileReader are in CRAMFileIndexTest @@ -229,4 +230,14 @@ public void testCRAMReader7_WithoutCRAMIndex() throws IOException { CRAMFileReader reader = new CRAMFileReader(CRAM_WITHOUT_CRAI, indexFile, REFERENCE, ValidationStringency.STRICT); reader.getIndex(); } + + @Test + public void testCramIteratorWithoutCallingHasNextFirst() throws IOException { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(false, SAMFileHeader.SortOrder.unsorted); + builder.addFrag("1", 0, 2, false); + final CRAMFileReader reader = CRAMTestUtils.writeAndReadFromInMemoryCram(builder); + final SAMRecordIterator iterator = reader.getIterator(); + Assert.assertNotNull(iterator.next()); + Assert.assertThrows(NoSuchElementException.class, iterator::next); + } } diff --git a/src/test/java/htsjdk/samtools/CRAMTestUtils.java b/src/test/java/htsjdk/samtools/CRAMTestUtils.java new file mode 100644 index 0000000000..b3d80ff487 --- /dev/null +++ b/src/test/java/htsjdk/samtools/CRAMTestUtils.java @@ -0,0 +1,66 @@ +package htsjdk.samtools; + +import htsjdk.samtools.cram.ref.CRAMReferenceSource; +import htsjdk.samtools.cram.ref.ReferenceSource; +import htsjdk.samtools.reference.InMemoryReferenceSequenceFile; +import htsjdk.samtools.seekablestream.SeekableStream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +public final class CRAMTestUtils { + + //private constructor since this is a utility class + private CRAMTestUtils(){}; + + /** + * Write a collection of SAMRecords into an in memory Cram file and then open a reader over it + * @param records a Collection of SAMRecords + * @param ref a set of bases to use as the single reference contig named "chr1" + * @return a CRAMFileReader reading from an in memory buffer that has had the records written into it + */ + public static CRAMFileReader writeAndReadFromInMemoryCram(Collection records, byte[] ref) throws IOException { + InMemoryReferenceSequenceFile refFile = new InMemoryReferenceSequenceFile(); + refFile.add("chr1", ref); + ReferenceSource source = new ReferenceSource(refFile); + final SAMFileHeader header = records.iterator().next().getHeader(); + return writeAndReadFromInMemoryCram(records, source, header); + } + + /** + * Write a collection of SAMRecords into an in memory Cram file and then open a reader over it + * @param records a SAMRecordSetBuilder which has been initialized with records + * @return a CRAMFileReader reading from an in memory buffer that has had the records written into it, uses a fake reference with all A's + */ + public static CRAMFileReader writeAndReadFromInMemoryCram(SAMRecordSetBuilder records) throws IOException { + return writeAndReadFromInMemoryCram(records.getRecords(), getFakeReferenceSource(), records.getHeader()); + } + + private static CRAMFileReader writeAndReadFromInMemoryCram(Collection records, CRAMReferenceSource source, SAMFileHeader header) throws IOException { + try(ByteArrayOutputStream baos = new ByteArrayOutputStream(); + CRAMFileWriter cramFileWriter = new CRAMFileWriter(baos, source, header, "whatever")){ + + records.forEach(cramFileWriter::addAlignment); + + //force a flush before reading from the buffer + cramFileWriter.close(); + + return new CRAMFileReader(new ByteArrayInputStream(baos.toByteArray()), (SeekableStream) null, source, ValidationStringency.SILENT); + } + } + + /** + * return a CRAMReferenceSource that returns all A's for any sequence queried + */ + public static CRAMReferenceSource getFakeReferenceSource() { + return (sequenceRecord, tryNameVariants) -> { + byte[] bases = new byte[sequenceRecord.getSequenceLength()]; + Arrays.fill(bases, (byte)'A'); + return bases; + }; + } +} diff --git a/src/test/java/htsjdk/samtools/CachingBAMFileIndexTest.java b/src/test/java/htsjdk/samtools/CachingBAMFileIndexTest.java new file mode 100644 index 0000000000..e810b25aea --- /dev/null +++ b/src/test/java/htsjdk/samtools/CachingBAMFileIndexTest.java @@ -0,0 +1,123 @@ +package htsjdk.samtools; + + +import htsjdk.HtsjdkTest; +import htsjdk.samtools.util.IOUtil; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class CachingBAMFileIndexTest extends HtsjdkTest { + + /** + * test case to reproduce https://github.com/samtools/htsjdk/issues/1127 + * this tests for a bug that was hidden on human data pre-hg38 due to a weird interaction between WeakHashMap Integer interning + */ + @Test + public void testCachingBamFileIndextest() throws IOException { + try(final CachingBAMFileIndex index = getIndexWith200Contigs()) { + Assert.assertNotNull(index.getQueryResults(1)); + System.gc(); + //contig 1 is never garbage collected because Integer(1) is interned by the jvm and never garbage collectable + Assert.assertNotNull(index.getQueryResults(1)); + + Assert.assertNotNull(index.getQueryResults(128)); + System.gc(); + //contig 128 is garbage collected and hits the bug because 128+ is not interned + Assert.assertNotNull(index.getQueryResults(128)); + } + } + + private static CachingBAMFileIndex getIndexWith200Contigs() throws IOException { + List contigs = IntStream.range(1, 200) + .mapToObj(i -> new SAMSequenceRecord(String.valueOf(i), 1000)) + .collect(Collectors.toList()); + final SAMSequenceDictionary dict = new SAMSequenceDictionary(contigs); + final SAMFileHeader header = new SAMFileHeader(dict); + header.setSortOrder(SAMFileHeader.SortOrder.coordinate); + + final SAMFileWriterFactory writerFactory = new SAMFileWriterFactory().setCreateIndex(true); + final File outBam = File.createTempFile("tmp", ".bam"); + try(final SAMFileWriter writer = writerFactory.makeWriter(header, true, outBam, null)){ + IntStream.range(1,200).mapToObj(i -> { + final SAMRecord record = new SAMRecord(header); + record.setReadName("name" + i); + record.setReferenceName(String.valueOf(i)); + record.setReadUnmappedFlag(false); + record.setAlignmentStart(1); + record.setCigarString("20M"); + return record; + }).forEach(writer::addAlignment); + } + + final File indexFile = new File(outBam.getParent(), IOUtil.basename(outBam) + BAMIndex.BAMIndexSuffix); + indexFile.deleteOnExit(); + outBam.deleteOnExit(); + return new CachingBAMFileIndex(indexFile, dict); + } + + @Test + public void testCacheHitsAndMissesTheExpectedNumberOfTimes() throws IOException { + try(final CachingBAMFileIndex index = getIndexWith200Contigs()) { + index.getQueryResults(1); + assertCacheStats(index, 0, 1); + + index.getQueryResults(1); + assertCacheStats(index, 1, 1); + + index.getQueryResults(150); + assertCacheStats(index, 1, 2); + + index.getQueryResults(150); + assertCacheStats(index,2,2); + + index.getQueryResults(150); + assertCacheStats(index,3,2); + + index.getQueryResults(1); + assertCacheStats(index, 3, 3); + + index.getQueryResults(1); + assertCacheStats(index, 4, 3); + + index.getQueryResults(1000); + assertCacheStats(index,4,4); + } + } + + @Test + public void testNullResultIsCached() throws IOException { + try(final CachingBAMFileIndex index = getIndexWith200Contigs()) { + BAMIndexContent queryResults = index.getQueryResults(1000); + Assert.assertNull(queryResults); + assertCacheStats(index, 0, 1); + + queryResults = index.getQueryResults(1000); + Assert.assertNull(queryResults); + assertCacheStats(index, 1, 1); + + queryResults = index.getQueryResults(1); + Assert.assertNotNull(queryResults); + assertCacheStats(index, 1, 2); + + queryResults = index.getQueryResults(1000); + Assert.assertNull(queryResults); + assertCacheStats(index, 1, 3); + + queryResults = index.getQueryResults(1000); + Assert.assertNull(queryResults); + assertCacheStats(index, 2, 3); + } + } + + private static void assertCacheStats(CachingBAMFileIndex index, int hits, int misses) { + Assert.assertEquals(index.getCacheHits(), hits, "cache hits didn't match expected"); + Assert.assertEquals(index.getCacheMisses(), misses, "cache misses didn't match expected"); + } + +} \ No newline at end of file diff --git a/src/test/java/htsjdk/samtools/CramContainerHeaderIteratorTest.java b/src/test/java/htsjdk/samtools/CramContainerHeaderIteratorTest.java new file mode 100644 index 0000000000..5f8be41179 --- /dev/null +++ b/src/test/java/htsjdk/samtools/CramContainerHeaderIteratorTest.java @@ -0,0 +1,67 @@ +package htsjdk.samtools; + +import htsjdk.HtsjdkTest; +import htsjdk.samtools.cram.build.CramContainerHeaderIterator; +import htsjdk.samtools.cram.build.CramContainerIterator; +import htsjdk.samtools.cram.structure.Container; +import htsjdk.samtools.cram.structure.ContainerIO; +import htsjdk.samtools.cram.structure.CramHeader; +import htsjdk.samtools.seekablestream.SeekableFileStream; +import htsjdk.samtools.util.Iterables; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +public class CramContainerHeaderIteratorTest extends HtsjdkTest { + @Test + public void test() throws IOException { + final File cramFile = new File("src/test/resources/htsjdk/samtools/cram/NA12878.20.21.1-100.100-SeqsPerSlice.0-unMapped.cram"); + CramHeader expectedHeader; + List fullContainers; + try (SeekableFileStream seekableFileStream = new SeekableFileStream(cramFile)) { + CramContainerIterator iterator = new CramContainerIterator(seekableFileStream); + expectedHeader = iterator.getCramHeader(); + fullContainers = Iterables.slurp(iterator); + } + CramHeader actualHeader; + List headerOnlyContainers; + try (SeekableFileStream seekableFileStream = new SeekableFileStream(cramFile)) { + CramContainerHeaderIterator iterator = new CramContainerHeaderIterator(seekableFileStream); + actualHeader = iterator.getCramHeader(); + headerOnlyContainers = Iterables.slurp(iterator); + } + Assert.assertEquals(actualHeader, expectedHeader); + Assert.assertEquals(fullContainers.size(), headerOnlyContainers.size()); + for (int i = 0; i < fullContainers.size(); i++) { + Container fullContainer = fullContainers.get(i); + Container headerOnlyContainer = headerOnlyContainers.get(i); + Assert.assertEquals(headerOnlyContainer.containerByteSize, fullContainer.containerByteSize); + Assert.assertEquals(headerOnlyContainer.sequenceId, fullContainer.sequenceId); + Assert.assertEquals(headerOnlyContainer.alignmentStart, fullContainer.alignmentStart); + Assert.assertEquals(headerOnlyContainer.alignmentSpan, fullContainer.alignmentSpan); + Assert.assertEquals(headerOnlyContainer.nofRecords, fullContainer.nofRecords); + Assert.assertEquals(headerOnlyContainer.globalRecordCounter, fullContainer.globalRecordCounter); + Assert.assertEquals(headerOnlyContainer.bases, fullContainer.bases); + Assert.assertEquals(headerOnlyContainer.blockCount, fullContainer.blockCount); + Assert.assertEquals(headerOnlyContainer.landmarks, fullContainer.landmarks); + Assert.assertEquals(headerOnlyContainer.checksum, fullContainer.checksum); + Assert.assertEquals(headerOnlyContainer.offset, fullContainer.offset); + // unpopulated fields + Assert.assertNull(headerOnlyContainer.blocks); + Assert.assertNull(headerOnlyContainer.header); + Assert.assertNull(headerOnlyContainer.slices); + // try to read a container from the offset to check it's correct + try (SeekableFileStream seekableFileStream = new SeekableFileStream(cramFile)) { + seekableFileStream.seek(headerOnlyContainer.offset); + Container container = ContainerIO.readContainer(actualHeader.getVersion(), seekableFileStream); + Assert.assertEquals(container.alignmentStart, fullContainer.alignmentStart); + Assert.assertEquals(container.alignmentSpan, fullContainer.alignmentSpan); + Assert.assertEquals(container.nofRecords, fullContainer.nofRecords); + Assert.assertEquals(container.checksum, fullContainer.checksum); + } + } + } +} diff --git a/src/test/java/htsjdk/samtools/SAMFileHeaderTest.java b/src/test/java/htsjdk/samtools/SAMFileHeaderTest.java index 86946d0f5d..911a7bd24c 100644 --- a/src/test/java/htsjdk/samtools/SAMFileHeaderTest.java +++ b/src/test/java/htsjdk/samtools/SAMFileHeaderTest.java @@ -23,7 +23,9 @@ package htsjdk.samtools; import htsjdk.HtsjdkTest; +import htsjdk.samtools.util.BufferedLineReader; import org.testng.Assert; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Arrays; @@ -31,7 +33,7 @@ public class SAMFileHeaderTest extends HtsjdkTest { @Test - public void testSortOrder() { + public void testSortOrderManualSetting() { final SAMFileHeader header = new SAMFileHeader(); header.setSortOrder(SAMFileHeader.SortOrder.coordinate); @@ -45,6 +47,21 @@ public void testSortOrder() { header.setAttribute(SAMFileHeader.SORT_ORDER_TAG, SAMFileHeader.SortOrder.coordinate); Assert.assertEquals(header.getSortOrder(), SAMFileHeader.SortOrder.coordinate); Assert.assertEquals(header.getAttribute(SAMFileHeader.SORT_ORDER_TAG), SAMFileHeader.SortOrder.coordinate.name()); + + header.setAttribute(SAMFileHeader.SORT_ORDER_TAG, "UNKNOWN"); + Assert.assertEquals(header.getSortOrder(), SAMFileHeader.SortOrder.unknown); + Assert.assertEquals(header.getAttribute(SAMFileHeader.SORT_ORDER_TAG), + SAMFileHeader.SortOrder.unknown.name()); + + header.setAttribute(SAMFileHeader.SORT_ORDER_TAG, "uNknOWn"); + Assert.assertEquals(header.getSortOrder(), SAMFileHeader.SortOrder.unknown); + Assert.assertEquals(header.getAttribute(SAMFileHeader.SORT_ORDER_TAG), + SAMFileHeader.SortOrder.unknown.name()); + + header.setAttribute(SAMFileHeader.SORT_ORDER_TAG, "cOoRdinate"); + Assert.assertEquals(header.getSortOrder(), SAMFileHeader.SortOrder.unknown); + Assert.assertEquals(header.getAttribute(SAMFileHeader.SORT_ORDER_TAG), + SAMFileHeader.SortOrder.unknown.name()); } @Test @@ -81,4 +98,76 @@ public void testGetSequenceIfNameIsNotFound() { Assert.assertNull(header.getSequence("chr2")); } + + @Test + public void testWrongTag() { + String[] testData = new String[]{ + "@hd\tVN:1.0\tSO:unsorted\n", + "@sq\tSN:chrM\tLN:16571\n", + "@rg\tID:1\tSM:sample1\n", + "@pg\tID:1\tPN:A\n", + "@co\tVN:1.0\tSO:unsorted\n" + }; + for (String stringHeader : testData) { + SAMTextHeaderCodec codec = new SAMTextHeaderCodec(); + SAMFileHeader header = codec.decode(BufferedLineReader.fromString(stringHeader), null); + String validationErrors = header.getValidationErrors().toString(); + Assert.assertTrue(validationErrors.contains("Unrecognized header record type")); + } + + } + + @DataProvider(name = "DataForWrongTagTests") + public Object[][] dataForWrongTagTests() { + return new Object[][] { + {"@HD\tVN:1.0\tSO:UNSORTED\n"}, + {"@HD\tVN:1.0\tSO:FALSE\n"}, + {"@HD\tVN:1.0\tSO:COORDINATE\n"}, + {"@HD\tVN:1.0\tSO:uNknOWn\n"}, + {"@HD\tVN:1.0\tSO:cOoRdinate\n"}, + }; + } + + @Test(dataProvider = "DataForWrongTagTests") + public void testSortOrderCodecSetting(String hdr) { + String validString = "@HD\tVN:1.0\tSO:unknown\n"; + + SAMTextHeaderCodec codec = new SAMTextHeaderCodec(); + SAMFileHeader header = codec.decode(BufferedLineReader.fromString(validString), null); + + header.setSortOrder(SAMFileHeader.SortOrder.coordinate); + Assert.assertEquals(header.getSortOrder(), SAMFileHeader.SortOrder.coordinate); + Assert.assertEquals(header.getAttribute(SAMFileHeader.SORT_ORDER_TAG), SAMFileHeader.SortOrder.coordinate.name()); + + header.setSortOrder(SAMFileHeader.SortOrder.unsorted); + Assert.assertEquals(header.getSortOrder(), SAMFileHeader.SortOrder.unsorted); + Assert.assertEquals(header.getAttribute(SAMFileHeader.SORT_ORDER_TAG), SAMFileHeader.SortOrder.unsorted.name()); + + header.setAttribute(SAMFileHeader.SORT_ORDER_TAG, "badname"); + Assert.assertEquals(header.getSortOrder(), SAMFileHeader.SortOrder.unknown); + Assert.assertEquals(header.getAttribute(SAMFileHeader.SORT_ORDER_TAG), SAMFileHeader.SortOrder.unknown.name()); + + header = codec.decode(BufferedLineReader.fromString(hdr), null); + Assert.assertTrue(header.getSortOrder().toString().equals("unknown")); + } + + @Test(dataProvider = "DataForWrongTagTests", expectedExceptions = SAMFormatException.class) + public void testValidationStringencyStrict(String stringHeader) { + SAMTextHeaderCodec codec = new SAMTextHeaderCodec(); + codec.setValidationStringency(ValidationStringency.STRICT); + codec.decode(BufferedLineReader.fromString(stringHeader), null); + } + + @Test(dataProvider = "DataForWrongTagTests") + public void testValidationStringencyLenientAndSilent(String stringHeader) { + SAMTextHeaderCodec codec = new SAMTextHeaderCodec(); + + codec.setValidationStringency(ValidationStringency.LENIENT); + SAMFileHeader headerLenient = codec.decode(BufferedLineReader.fromString(stringHeader), null); + Assert.assertTrue(headerLenient.getSortOrder().equals(SAMFileHeader.SortOrder.unknown)); + + codec.setValidationStringency(ValidationStringency.SILENT); + SAMFileHeader headerSilent = codec.decode(BufferedLineReader.fromString(stringHeader), null); + Assert.assertTrue(headerSilent.getSortOrder().equals(SAMFileHeader.SortOrder.unknown)); + } } diff --git a/src/test/java/htsjdk/samtools/SAMFileWriterFactoryTest.java b/src/test/java/htsjdk/samtools/SAMFileWriterFactoryTest.java index 9abf93200b..adc3de7fc2 100644 --- a/src/test/java/htsjdk/samtools/SAMFileWriterFactoryTest.java +++ b/src/test/java/htsjdk/samtools/SAMFileWriterFactoryTest.java @@ -337,7 +337,7 @@ public void testMakeWriterPath(String extension) throws Exception { Files.deleteIfExists(outputPath); final SAMFileHeader header = new SAMFileHeader(); final SAMFileWriterFactory factory = createWriterFactoryWithOptions(header); - final File referenceFile = new File(TEST_DATA_DIR, "hg19mini.fasta"); + final Path referenceFile = new File(TEST_DATA_DIR, "hg19mini.fasta").toPath(); int nRecs; try (final SAMFileWriter samWriter = factory.makeWriter(header, false, outputPath, referenceFile)) { @@ -347,6 +347,24 @@ public void testMakeWriterPath(String extension) throws Exception { } } + @Test(dataProvider="bamOrCramWriter") + public void testMakeWriterPathAndReferencePath(String extension) throws Exception { + final String referenceName = "hg19mini.fasta"; + try (FileSystem jimfs = Jimfs.newFileSystem(Configuration.unix())) { + Path outputPath = jimfs.getPath("testMakeWriterPath" + extension); + Files.deleteIfExists(outputPath); + final SAMFileHeader header = new SAMFileHeader(); + final SAMFileWriterFactory factory = createWriterFactoryWithOptions(header); + final Path referencePath = jimfs.getPath(referenceName); + Files.copy(new File(TEST_DATA_DIR, referenceName).toPath(), referencePath); + + int nRecs; + try (final SAMFileWriter samWriter = factory.makeWriter(header, false, outputPath, referencePath)) { + nRecs = fillSmallBam(samWriter); + } + verifyWriterOutput(outputPath, new ReferenceSource(referencePath), nRecs, true); + } + } @Test public void testMakeCRAMWriterWithOptions() throws Exception { diff --git a/src/test/java/htsjdk/samtools/SAMIntegerTagTest.java b/src/test/java/htsjdk/samtools/SAMIntegerTagTest.java index 3fa38df62c..c211d32878 100644 --- a/src/test/java/htsjdk/samtools/SAMIntegerTagTest.java +++ b/src/test/java/htsjdk/samtools/SAMIntegerTagTest.java @@ -348,7 +348,7 @@ private void testRoundtripIntegerAttribute(final Number value, final FORMAT form w = new SAMFileWriterFactory().makeBAMWriter(header, false, baos); break; case CRAM: - w = new SAMFileWriterFactory().makeCRAMWriter(header, baos, null); + w = new SAMFileWriterFactory().makeCRAMWriter(header, baos, (File) null); break; default: throw new RuntimeException("Unknown format: " + format); diff --git a/src/test/java/htsjdk/samtools/SAMRecordUnitTest.java b/src/test/java/htsjdk/samtools/SAMRecordUnitTest.java index e9b599b353..decf011792 100644 --- a/src/test/java/htsjdk/samtools/SAMRecordUnitTest.java +++ b/src/test/java/htsjdk/samtools/SAMRecordUnitTest.java @@ -25,18 +25,25 @@ package htsjdk.samtools; import htsjdk.HtsjdkTest; +import htsjdk.samtools.cram.build.CramIO; import htsjdk.samtools.util.BinaryCodec; +import htsjdk.samtools.util.IOUtil; import htsjdk.samtools.util.TestUtil; +import htsjdk.utils.TestNGUtils; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.*; -import java.util.Arrays; -import java.util.List; +import java.lang.reflect.Array; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; public class SAMRecordUnitTest extends HtsjdkTest { + private static final String ARRAY_TAG = "xa"; + @DataProvider(name = "serializationTestData") public Object[][] getSerializationTestData() { return new Object[][] { @@ -568,6 +575,70 @@ public void testInvalidAlignmentStartValidation() { Assert.assertTrue(validationErrors != null && validationErrors.size() == 1); } + @DataProvider + public Object [][] binFieldValidationData() { + return new Object[][]{ + {1519, 4681, 51, 16571, false}, + {1519, 4685, 51, 16571, true}, + {16500, 4681, 51, 16571, true}, + {100000, 4687, 1000, 500_000_000, false}, + {300000000, 44, 1000000, 500_000_000, false}, + {300000000, 100000, 1000000, 500_000_000, true}, + + {100000, 4681, 1000, 1000_000_000, false}, + {100000, 4681, 10000, 2000_000_000, false}, + }; + } + + @Test(dataProvider = "binFieldValidationData") + public void testBinFieldValidation(final int alignmentStart, + final int bin, + final int readLength, + final int referenceLength, + final boolean isErrorExpected) { + final SAMRecord sam = createSamRecordWithHeaderAndBin(alignmentStart, bin, readLength, referenceLength); + + final List errorList = sam.isValid(false); + + final boolean hasError = Optional.ofNullable(errorList) + .map(Collection::stream) + .map(stream -> stream.anyMatch(error -> error.getType() == SAMValidationError.Type.INVALID_INDEXING_BIN)) + .orElse(false); + Assert.assertEquals(hasError, isErrorExpected); + } + + private SAMRecord createSamRecordWithHeaderAndBin(final int alignmentStart, + final int bin, + final int readLength, + final int referenceLength) { + final SAMRecord rec = createSamRecord(alignmentStart, readLength); + rec.setIndexingBin(bin); + + final String referenceName = "Sheila"; + rec.setReferenceName(referenceName); + + final SAMFileHeader header = createHeaderWithOneReference(referenceName, referenceLength); + rec.setHeader(header); + + return rec; + } + + private SAMRecord createSamRecord(final int alignmentStart, final int readLength) { + final SAMRecordSetBuilder recordsBuilder = new SAMRecordSetBuilder(); + recordsBuilder.setReadLength(readLength); + return recordsBuilder.addFrag("test", 0, alignmentStart, false, false, readLength + "M", null, 2); + } + + private SAMFileHeader createHeaderWithOneReference(final String referenceName, final int referenceLength) { + final SAMSequenceRecord sequenceRecord = new SAMSequenceRecord(referenceName, referenceLength); + final List records = Collections.singletonList(sequenceRecord); + final SAMSequenceDictionary dict = new SAMSequenceDictionary(records); + final SAMFileHeader header = new SAMFileHeader(dict); + final SAMReadGroupRecord groupRecord = new SAMReadGroupRecord("1"); + header.setReadGroups(Collections.singletonList(groupRecord)); + return header; + } + // ----------------- NULL header tests --------------------- @Test @@ -1102,4 +1173,76 @@ private Object[][] hasAttributeTestData() throws IOException { public void testHasAttribute(final SAMRecord samRecord, final String tag, final boolean expectedHasAttribute) { Assert.assertEquals(samRecord.hasAttribute(tag), expectedHasAttribute); } + + @Test + public void test_setAttribute_empty_array() { + final SAMFileHeader header = new SAMFileHeader(); + final SAMRecord record = new SAMRecord(header); + Assert.assertNull(record.getStringAttribute(ARRAY_TAG)); + record.setAttribute(ARRAY_TAG, new int[0]); + Assert.assertNotNull(record.getSignedIntArrayAttribute(ARRAY_TAG)); + Assert.assertEquals(record.getSignedIntArrayAttribute(ARRAY_TAG), new int[0]); + Assert.assertEquals(record.getAttribute(ARRAY_TAG), new char[0]); + record.setAttribute(ARRAY_TAG, null); + Assert.assertNull(record.getStringAttribute(ARRAY_TAG)); + } + + private static Object[][] getEmptyArrays() { + return new Object[][]{ + {new int[0], int[].class}, + {new short[0], short[].class}, + {new byte[0], byte[].class}, + {new float[0], float[].class}, + }; + } + + private static Object[][] getFileExtensions(){ + return new Object[][]{ + {BamFileIoUtils.BAM_FILE_EXTENSION}, {IOUtil.SAM_FILE_EXTENSION}, {CramIO.CRAM_FILE_EXTENSION} + }; + } + + @DataProvider + public Object[][] getEmptyArraysAndExtensions(){ + return TestNGUtils.cartesianProduct(getEmptyArrays(), getFileExtensions()); + } + + @Test(dataProvider = "getEmptyArraysAndExtensions") + public void testWriteSamWithEmptyArray(Object emptyArray, Class arrayClass, String fileExtension) throws IOException { + Assert.assertEquals(emptyArray.getClass(), arrayClass); + Assert.assertEquals(Array.getLength(emptyArray), 0); + + final SAMRecordSetBuilder samRecords = new SAMRecordSetBuilder(); + samRecords.addFrag("Read", 0, 100, false); + final SAMRecord record = samRecords.getRecords().iterator().next(); + record.setAttribute(ARRAY_TAG, emptyArray); + checkArrayIsEmpty(ARRAY_TAG, record, arrayClass); + + final Path tmp = Files.createTempFile("tmp", fileExtension); + IOUtil.deleteOnExit(tmp); + + final SAMFileWriterFactory writerFactory = new SAMFileWriterFactory() + .setCreateMd5File(false) + .setCreateIndex(false); + final Path reference = IOUtil.getPath("src/test/resources/htsjdk/samtools/one-contig.fasta"); + try (final SAMFileWriter samFileWriter = writerFactory.makeWriter(samRecords.getHeader(), false, tmp, reference)) { + samFileWriter.addAlignment(record); + } + + try (final SamReader reader = SamReaderFactory.makeDefault() + .referenceSequence(reference) + .open(tmp)) { + final SAMRecordIterator iterator = reader.iterator(); + Assert.assertTrue(iterator.hasNext()); + final SAMRecord recordFromDisk = iterator.next(); + checkArrayIsEmpty(ARRAY_TAG, recordFromDisk, arrayClass); + } + } + + private static void checkArrayIsEmpty(String arrayTag, SAMRecord recordFromDisk, Class expectedClass) { + final Object attribute = recordFromDisk.getAttribute(arrayTag); + Assert.assertNotNull(attribute); + Assert.assertEquals(attribute.getClass(), expectedClass); + Assert.assertEquals(Array.getLength(attribute), 0); + } } diff --git a/src/test/java/htsjdk/samtools/SAMSequenceDictionaryTest.java b/src/test/java/htsjdk/samtools/SAMSequenceDictionaryTest.java index a8e60ed501..a0063cc938 100644 --- a/src/test/java/htsjdk/samtools/SAMSequenceDictionaryTest.java +++ b/src/test/java/htsjdk/samtools/SAMSequenceDictionaryTest.java @@ -31,10 +31,6 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; import java.io.StringReader; import java.io.StringWriter; import java.util.Arrays; @@ -59,38 +55,7 @@ public void testAliases() { Assert.assertNull(dict.getSequence("chr2")); } - /** - * should be saved as XML - * - *

-     * 12
-     * 
- * - * @throws JAXBException - */ - @Test - public void testXmlSeralization() throws JAXBException { - // create dict - final SAMSequenceRecord ssr1 = new SAMSequenceRecord("1", 1); - ssr1.setMd5("68b329da9893e34099c7d8ad5cb9c940"); - ssr1.setAssembly("as"); - ssr1.setSpecies("sp"); - final SAMSequenceRecord ssr2 = new SAMSequenceRecord("2", 1); - final StringWriter xmlWriter = new StringWriter(); - final SAMSequenceDictionary dict1 = new SAMSequenceDictionary( - Arrays.asList(ssr1, ssr2)); - // create jaxb context - JAXBContext jaxbContext = JAXBContext - .newInstance(SAMSequenceDictionary.class); - // save to XML - Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); - jaxbMarshaller.marshal(dict1, xmlWriter); - // reload XML - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - final SAMSequenceDictionary dict2 = (SAMSequenceDictionary) jaxbUnmarshaller - .unmarshal(new StringReader(xmlWriter.toString())); - Assert.assertEquals(dict1, dict2); - } + @DataProvider(name="testMergeDictionariesData") public Object[][] testMergeDictionariesData(){ diff --git a/src/test/java/htsjdk/samtools/SAMTextReaderTest.java b/src/test/java/htsjdk/samtools/SAMTextReaderTest.java index 142eea32c1..36826d0925 100644 --- a/src/test/java/htsjdk/samtools/SAMTextReaderTest.java +++ b/src/test/java/htsjdk/samtools/SAMTextReaderTest.java @@ -27,12 +27,15 @@ import htsjdk.samtools.util.CloseableIterator; import htsjdk.samtools.util.CloserUtil; import org.testng.Assert; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; public class SAMTextReaderTest extends HtsjdkTest { + private static final String ARRAY_TAG = "xa"; + // Simple input, spot check that parsed correctly, and make sure nothing blows up. @Test public void testBasic() throws Exception { @@ -135,4 +138,21 @@ public void testTagWithColon() { Assert.assertEquals(recFromText.getAttribute(SAMTag.CQ.name()), valueWithColons); CloserUtil.close(reader); } + + @DataProvider + public Object[][] getRecordsWithArrays(){ + final String recordBase = "Read\t4\tchr1\t1\t0\t*\t*\t0\t0\tG\t%\t"; + return new Object[][]{ + {recordBase + ARRAY_TAG + ":B:i", new int[0]}, + {recordBase + ARRAY_TAG + ":B:i,", new int[0]}, + {recordBase + ARRAY_TAG + ":B:i,1,2,3,", new int[]{1,2,3}}, + }; + } + + @Test(dataProvider = "getRecordsWithArrays") + public void testSamRecordCanHandleArrays(String samRecord, Object array){ + final SAMLineParser samLineParser = new SAMLineParser(new SAMFileHeader()); + final SAMRecord record = samLineParser.parseLine(samRecord); + Assert.assertEquals(record.getAttribute(ARRAY_TAG), array); + } } diff --git a/src/test/java/htsjdk/samtools/SAMTextWriterTest.java b/src/test/java/htsjdk/samtools/SAMTextWriterTest.java index 5c9ff28cde..1ee916f58f 100644 --- a/src/test/java/htsjdk/samtools/SAMTextWriterTest.java +++ b/src/test/java/htsjdk/samtools/SAMTextWriterTest.java @@ -34,7 +34,7 @@ public class SAMTextWriterTest extends HtsjdkTest { - private SAMRecordSetBuilder getSAMReader(final boolean sortForMe, final SAMFileHeader.SortOrder sortOrder) { + private SAMRecordSetBuilder getSamRecordSet(final boolean sortForMe, final SAMFileHeader.SortOrder sortOrder) { final SAMRecordSetBuilder ret = new SAMRecordSetBuilder(sortForMe, sortOrder); ret.addPair("readB", 20, 200, 300); ret.addPair("readA", 20, 100, 150); @@ -45,7 +45,7 @@ private SAMRecordSetBuilder getSAMReader(final boolean sortForMe, final SAMFileH @Test public void testNullHeader() throws Exception { - final SAMRecordSetBuilder recordSetBuilder = getSAMReader(true, SAMFileHeader.SortOrder.coordinate); + final SAMRecordSetBuilder recordSetBuilder = getSamRecordSet(true, SAMFileHeader.SortOrder.coordinate); for (final SAMRecord rec : recordSetBuilder.getRecords()) { rec.setHeader(null); } @@ -77,7 +77,7 @@ private void doTest(final SAMRecordSetBuilder recordSetBuilder) throws Exception } private void doTest(final SamFlagField samFlagField) throws Exception { - doTest(getSAMReader(true, SAMFileHeader.SortOrder.coordinate), samFlagField); + doTest(getSamRecordSet(true, SAMFileHeader.SortOrder.coordinate), samFlagField); } private void doTest(final SAMRecordSetBuilder recordSetBuilder, final SamFlagField samFlagField) throws Exception { @@ -128,4 +128,12 @@ private void doTest(final SAMRecordSetBuilder recordSetBuilder, final SamFlagFie Assert.assertFalse(newSAMIt.hasNext()); inputSAM.close(); } + + @Test + public void testEmptyArrayAttributeHasNoCommaWhenWrittenToSAM(){ + final SAMFileHeader header = new SAMFileHeader(); + final SAMRecord record = new SAMRecord(header); + record.setAttribute("xa", new int[0]); + Assert.assertTrue(record.getSAMString().endsWith("xa:B:i\n")); + } } diff --git a/src/test/java/htsjdk/samtools/SamFilesTest.java b/src/test/java/htsjdk/samtools/SamFilesTest.java index e7c1919d41..a386c9db39 100644 --- a/src/test/java/htsjdk/samtools/SamFilesTest.java +++ b/src/test/java/htsjdk/samtools/SamFilesTest.java @@ -3,6 +3,7 @@ import java.nio.file.Path; import htsjdk.HtsjdkTest; +import htsjdk.samtools.util.IOUtil; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -88,6 +89,6 @@ public Object[][] getFilesAndIndicies() throws IOException { @Test(dataProvider ="filesAndIndicies") public void testIndexSymlinking(File bam, File expected_index) { Assert.assertEquals(SamFiles.findIndex(bam), expected_index); - Assert.assertEquals(SamFiles.findIndex(bam.toPath()), expected_index == null ? null : expected_index.toPath()); + Assert.assertEquals(SamFiles.findIndex(bam.toPath()), IOUtil.toPath(expected_index)); } } diff --git a/src/test/java/htsjdk/samtools/SamReaderFactoryTest.java b/src/test/java/htsjdk/samtools/SamReaderFactoryTest.java index c244f3c8b4..87372f47f0 100644 --- a/src/test/java/htsjdk/samtools/SamReaderFactoryTest.java +++ b/src/test/java/htsjdk/samtools/SamReaderFactoryTest.java @@ -1,17 +1,16 @@ package htsjdk.samtools; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; + import htsjdk.HtsjdkTest; +import htsjdk.samtools.SAMFileHeader.SortOrder; import htsjdk.samtools.cram.ref.ReferenceSource; import htsjdk.samtools.seekablestream.ISeekableStreamFactory; import htsjdk.samtools.seekablestream.SeekableFileStream; import htsjdk.samtools.seekablestream.SeekableHTTPStream; import htsjdk.samtools.seekablestream.SeekableStreamFactory; import htsjdk.samtools.util.*; -import java.net.URI; -import java.nio.ByteBuffer; -import java.nio.channels.SeekableByteChannel; -import java.nio.file.Paths; -import java.util.function.Function; import htsjdk.samtools.util.zip.InflaterFactory; import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -23,12 +22,16 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.FileSystem; +import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.nio.file.Paths; +import java.util.*; +import java.util.concurrent.*; import java.util.function.BiFunction; +import java.util.function.Function; import java.util.zip.Inflater; public class SamReaderFactoryTest extends HtsjdkTest { @@ -50,9 +53,10 @@ public void variousFormatReaderInflatorFactoryTest() throws IOException { final String inputFile = "compressed.bam"; final int[] inflateCalls = {0}; //Note: using an array is a HACK to fool the compiler class MyInflater extends Inflater { - MyInflater(boolean gzipCompatible){ + MyInflater(boolean gzipCompatible) { super(gzipCompatible); } + @Override public int inflate(byte[] b, int off, int len) throws java.util.zip.DataFormatException { inflateCalls[0]++; @@ -68,13 +72,14 @@ public Inflater makeInflater(final boolean gzipCompatible) { final File input = new File(TEST_DATA_DIR, inputFile); try (final SamReader reader = SamReaderFactory.makeDefault().inflaterFactory(myInflaterFactory).open(input)) { - for (final SAMRecord ignored : reader) { } + for (final SAMRecord ignored : reader) { + } } Assert.assertNotEquals(inflateCalls[0], 0, "Not using Inflater from InflateFactory on file : " + inputFile); } private int countRecordsInQueryInterval(final SamReader reader, final QueryInterval query) { - final SAMRecordIterator iter = reader.queryOverlapping(new QueryInterval[] { query }); + final SAMRecordIterator iter = reader.queryOverlapping(new QueryInterval[]{query}); int count = 0; while (iter.hasNext()) { iter.next(); @@ -97,22 +102,22 @@ private int countRecords(final SamReader reader) { private static SeekableByteChannel addHeader(SeekableByteChannel input) { try { - int total = (int)input.size(); - final String comment = "@HD\tVN:1.0 SO:unsorted\n" + - "@SQ\tSN:chr1\tLN:101\n" + - "@SQ\tSN:chr2\tLN:101\n" + - "@SQ\tSN:chr3\tLN:101\n" + - "@RG\tID:0\tSM:JP was here\n"; + int total = (int) input.size(); + final String comment = "@HD\tVN:1.0 SO:unsorted\n" + + "@SQ\tSN:chr1\tLN:101\n" + + "@SQ\tSN:chr2\tLN:101\n" + + "@SQ\tSN:chr3\tLN:101\n" + + "@RG\tID:0\tSM:JP was here\n"; byte[] commentBuf = comment.getBytes(); - ByteBuffer buf = ByteBuffer.allocate(total + commentBuf.length); - buf.put(commentBuf); - input.position(0); - while (input.read(buf)>0) { - // read until EOF - } - buf.flip(); - return new SeekableByteChannelFromBuffer(buf); + ByteBuffer buf = ByteBuffer.allocate(total + commentBuf.length); + buf.put(commentBuf); + input.position(0); + while (input.read(buf) > 0) { + // read until EOF + } + buf.flip(); + return new SeekableByteChannelFromBuffer(buf); } catch (IOException x) { throw new RuntimeException(x); } @@ -122,9 +127,9 @@ private static SeekableByteChannel addHeader(SeekableByteChannel input) { public void testWrap() throws IOException { final Path input = Paths.get(TEST_DATA_DIR.getPath(), "noheader.sam"); final SamReader wrappedReader = - SamReaderFactory - .makeDefault() - .open(input, SamReaderFactoryTest::addHeader, null); + SamReaderFactory + .makeDefault() + .open(input, SamReaderFactoryTest::addHeader, null); int records = countRecords(wrappedReader); Assert.assertEquals(10, records); } @@ -192,11 +197,14 @@ public void samRecordFactoryTest(final String inputFile) throws IOException { reader.close(); Assert.assertTrue(i > 0); - if (inputFile.endsWith(".sam") || inputFile.endsWith(".sam.gz")) Assert.assertEquals(recordFactory.samRecordsCreated, i); - else if (inputFile.endsWith(".bam")) Assert.assertEquals(recordFactory.bamRecordsCreated, i); + if (inputFile.endsWith(".sam") || inputFile.endsWith(".sam.gz")) { + Assert.assertEquals(recordFactory.samRecordsCreated, i); + } else if (inputFile.endsWith(".bam")) { + Assert.assertEquals(recordFactory.bamRecordsCreated, i); + } } - @Test(expectedExceptions=IllegalStateException.class) + @Test(expectedExceptions = IllegalStateException.class) public void samRecordFactoryNullHeaderBAMTest() { final SAMRecordFactory recordFactory = new DefaultSAMRecordFactory(); recordFactory.createBAMRecord( @@ -215,7 +223,6 @@ public void samRecordFactoryNullHeaderBAMTest() { null); } - /** * Unit tests for asserting all permutations of data and index sources read the same records and header. */ @@ -235,7 +242,7 @@ public void samRecordFactoryNullHeaderBAMTest() { @DataProvider public Object[][] composeAllPermutationsOfSamInputResource() { - final List sources = new ArrayList(); + final List sources = new ArrayList<>(); for (final InputResource.Type dataType : InputResource.Type.values()) { if (dataType.equals(InputResource.Type.SRA_ACCESSION)) continue; @@ -282,22 +289,23 @@ private InputResource composeInputResourceForType(final InputResource.Type type, } } - final Set observedHeaders = new HashSet(); - final Set> observedRecordOrdering = new HashSet>(); + final Set observedHeaders = new HashSet<>(); + final Set> observedRecordOrdering = new HashSet<>(); @Test(dataProvider = "composeAllPermutationsOfSamInputResource") public void exhaustInputResourcePermutation(final SamInputResource resource) throws IOException { - final SamReader reader = SamReaderFactory.makeDefault().open(resource); - LOG.info(String.format("Reading from %s ...", resource)); - final List slurped = Iterables.slurp(reader); - final SAMFileHeader fileHeader = reader.getFileHeader(); - reader.hasIndex(); - reader.indexing().hasBrowseableIndex(); - reader.close(); - - /* Ensure all tests have read the same records in the same order or, if this is the first test, set it as the template. */ - observedHeaders.add(fileHeader); - observedRecordOrdering.add(slurped); + try(final SamReader reader = SamReaderFactory.makeDefault().open(resource)) { + LOG.info(String.format("Reading from %s ...", resource)); + final List slurped = Iterables.slurp(reader); + final SAMFileHeader fileHeader = reader.getFileHeader(); + reader.hasIndex(); + reader.indexing().hasBrowseableIndex(); + + /* Ensure all tests have read the same records in the same order or, if this is the first test, set it as the template. */ + observedHeaders.add(fileHeader); + observedRecordOrdering.add(slurped); + } + Assert.assertEquals(observedHeaders.size(), 1, "read different headers than other testcases"); Assert.assertEquals(observedRecordOrdering.size(), 1, "read different records than other testcases"); } @@ -311,7 +319,6 @@ public void openPath() throws IOException { LOG.info(String.format("Reading from %s ...", path)); records = Iterables.slurp(reader); fileHeader = reader.getFileHeader(); - reader.close(); } try (final SamReader fileReader = SamReaderFactory.makeDefault().open(localBam)) { @@ -322,41 +329,40 @@ public void openPath() throws IOException { } } - final Set> observedRecordOrdering1 = new HashSet>(); - final Set> observedRecordOrdering3 = new HashSet>(); - final Set> observedRecordOrdering20 = new HashSet>(); + final Set> observedRecordOrdering1 = new HashSet<>(); + final Set> observedRecordOrdering3 = new HashSet<>(); + final Set> observedRecordOrdering20 = new HashSet<>(); @Test(dataProvider = "composeAllPermutationsOfSamInputResource") public void queryInputResourcePermutation(final SamInputResource resource) throws IOException { - final SamReader reader = SamReaderFactory.makeDefault().open(resource); - LOG.info(String.format("Query from %s ...", resource)); - if (reader.hasIndex()) { - final StopWatch stopWatch = new StopWatch(); - stopWatch.start(); - final SAMRecordIterator q1 = reader.query("chr1", 500000, 100000000, true); - observedRecordOrdering1.add(Iterables.slurp(q1)); - q1.close(); - final SAMRecordIterator q20 = reader.query("chr20", 1, 1000000, true); - observedRecordOrdering20.add(Iterables.slurp(q20)); - q20.close(); - final SAMRecordIterator q3 = reader.query("chr3", 1, 10000000, true); - observedRecordOrdering3.add(Iterables.slurp(q3)); - q3.close(); - stopWatch.stop(); - LOG.info(String.format("Finished queries in %sms", stopWatch.getElapsedTime())); - - Assert.assertEquals(observedRecordOrdering1.size(), 1, "read different records for chromosome 1"); - Assert.assertEquals(observedRecordOrdering20.size(), 1, "read different records for chromosome 20"); - Assert.assertEquals(observedRecordOrdering3.size(), 1, "read different records for chromosome 3"); - } else if (resource.indexMaybe() != null) { - LOG.warn("Resource has an index source, but is not indexed: " + resource); - } else { - LOG.info("Skipping query operation: no index."); + try(final SamReader reader = SamReaderFactory.makeDefault().open(resource)) { + LOG.info(String.format("Query from %s ...", resource)); + if (reader.hasIndex()) { + final StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + final SAMRecordIterator q1 = reader.query("chr1", 500000, 100000000, true); + observedRecordOrdering1.add(Iterables.slurp(q1)); + q1.close(); + final SAMRecordIterator q20 = reader.query("chr20", 1, 1000000, true); + observedRecordOrdering20.add(Iterables.slurp(q20)); + q20.close(); + final SAMRecordIterator q3 = reader.query("chr3", 1, 10000000, true); + observedRecordOrdering3.add(Iterables.slurp(q3)); + q3.close(); + stopWatch.stop(); + LOG.info(String.format("Finished queries in %sms", stopWatch.getElapsedTime())); + + Assert.assertEquals(observedRecordOrdering1.size(), 1, "read different records for chromosome 1"); + Assert.assertEquals(observedRecordOrdering20.size(), 1, "read different records for chromosome 20"); + Assert.assertEquals(observedRecordOrdering3.size(), 1, "read different records for chromosome 3"); + } else if (resource.indexMaybe() != null) { + LOG.warn("Resource has an index source, but is not indexed: " + resource); + } else { + LOG.info("Skipping query operation: no index."); + } } - reader.close(); } - /** * A path that pretends it's not based upon a file. This helps in cases where we want to test branches * that apply to non-file based paths without actually having to use non-file based resources (like cloud urls) @@ -395,50 +401,52 @@ public void queryStreamingPathBamWithFileIndex() throws IOException { @Test public void customReaderFactoryTest() throws IOException { try { - CustomReaderFactory.setInstance(new CustomReaderFactory( - "https://www.googleapis.com/genomics/v1beta/reads/," + - "htsjdk.samtools.SamReaderFactoryTest$TestReaderFactory")); - final SamReader reader = SamReaderFactory.makeDefault().open( - SamInputResource.of( - "https://www.googleapis.com/genomics/v1beta/reads/?uncompressed.sam")); - int i = 0; - for (@SuppressWarnings("unused") final SAMRecord ignored : reader) { - ++i; - } - reader.close(); - - Assert.assertTrue(i > 0); + CustomReaderFactory.setInstance(new CustomReaderFactory( + "https://www.googleapis.com/genomics/v1beta/reads/," + + "htsjdk.samtools.SamReaderFactoryTest$TestReaderFactory")); + final SamReader reader = SamReaderFactory.makeDefault().open( + SamInputResource.of( + "https://www.googleapis.com/genomics/v1beta/reads/?uncompressed.sam")); + int i = 0; + for (@SuppressWarnings("unused") final SAMRecord ignored : reader) { + ++i; + } + reader.close(); + + Assert.assertTrue(i > 0); } finally { - CustomReaderFactory.resetToDefaultInstance(); + CustomReaderFactory.resetToDefaultInstance(); } } - + public static class TestReaderFactory implements CustomReaderFactory.ICustomReaderFactory { - @Override - public SamReader open(URL url) { - final File file = new File(TEST_DATA_DIR, url.getQuery()); - LOG.info("Opening customr reader for " + file.toString()); - return SamReaderFactory.makeDefault().open(file); - } - } - + @Override + public SamReader open(URL url) { + final File file = new File(TEST_DATA_DIR, url.getQuery()); + LOG.info("Opening customr reader for " + file.toString()); + return SamReaderFactory.makeDefault().open(file); + } + } + @Test public void inputResourceFromStringTest() throws IOException { - Assert.assertEquals(SamInputResource.of("http://test.url").data().type(), - InputResource.Type.URL); - Assert.assertEquals(SamInputResource.of("https://test.url").data().type(), - InputResource.Type.URL); - Assert.assertEquals(SamInputResource.of("ftp://test.url").data().type(), - InputResource.Type.URL); - Assert.assertEquals(SamInputResource.of("/a/b/c").data().type(), - InputResource.Type.FILE); + Assert.assertEquals(SamInputResource.of("http://test.url").data().type(), + InputResource.Type.URL); + Assert.assertEquals(SamInputResource.of("https://test.url").data().type(), + InputResource.Type.URL); + Assert.assertEquals(SamInputResource.of("ftp://test.url").data().type(), + InputResource.Type.URL); + Assert.assertEquals(SamInputResource.of("/a/b/c").data().type(), + InputResource.Type.FILE); } @Test public void testCRAMReaderFromURL() throws IOException { // get a CRAM reader with an index from a URL-backed resource getCRAMReaderFromInputResource( - (cramURL, indexURL) -> { return SamInputResource.of(cramURL).index(indexURL);}, + (cramURL, indexURL) -> { + return SamInputResource.of(cramURL).index(indexURL); + }, true, 3); } @@ -453,8 +461,7 @@ public void testCRAMReaderFromURLStream() throws IOException { return SamInputResource .of(streamFactory.getStreamFor(cramURL)) .index(streamFactory.getStreamFor(indexURL)); - } - catch (IOException e) { + } catch (IOException e) { throw new RuntimeIOException(e); } }, @@ -466,18 +473,47 @@ public void testCRAMReaderFromURLStream() throws IOException { public void testCRAMReaderFromURLNoIndexFile() throws IOException { // get just a CRAM reader (no index) from an URL-backed resource getCRAMReaderFromInputResource( - (cramURL, indexURL) -> { return SamInputResource.of(cramURL); }, - false, - 11); + (cramURL, indexURL) -> { + return SamInputResource.of(cramURL); + }, + false, + 11); } - @Test(expectedExceptions=RuntimeIOException.class) + @Test(expectedExceptions = RuntimeIOException.class) public void testCRAMReaderFromURLBadIndexFile() throws IOException { // deliberately specify a bad index file to ensure we get an IOException getCRAMReaderFromInputResource( - (cramURL, indexURL) -> { return SamInputResource.of(cramURL).index(new File("nonexistent.bai")); }, - true, - 3); + (cramURL, indexURL) -> { + return SamInputResource.of(cramURL).index(new File("nonexistent.bai")); + }, + true, + 3); + } + + @Test + public void testCRAMReaderWithCRAIFromNonFilePath() throws IOException { + final File cramFile = new File(TEST_DATA_DIR, "cram/cramQueryWithCRAI.cram"); + final File cramIndex = new File(TEST_DATA_DIR, "cram/cramQueryWithCRAI.cram.crai"); + final File referenceFile = new File(TEST_DATA_DIR, "cram/human_g1k_v37.20.21.10M-10M200k.fasta"); + + try (final FileSystem jimfs = Jimfs.newFileSystem(Configuration.unix())) { + final Path jimfsCRAM = jimfs.getPath("acram.cram"); + final Path jimfsCRAI = jimfs.getPath("acram.crai"); + + Files.copy(cramFile.toPath(), jimfsCRAM); + Files.copy(cramIndex.toPath(), jimfsCRAI); + + final SamReaderFactory factory = SamReaderFactory.makeDefault() + .referenceSource(new ReferenceSource(referenceFile)) + .validationStringency(ValidationStringency.SILENT); + + // force SamReaderFactory through the CRAM code path for a CRAM with an index that can't be rendered as a file + try (final SamReader cramReader = factory.open(jimfsCRAM)) { + final SAMRecordIterator samIt = cramReader.query("20", 1, 1, false); + Assert.assertNotNull(samIt); + }; + } } private void getCRAMReaderFromInputResource( @@ -495,8 +531,8 @@ private void getCRAMReaderFromInputResource( final SamReader reader = factory.open(getInputResource.apply(cramURL, indexURL)); int count = hasIndex ? - countRecordsInQueryInterval(reader, new QueryInterval(1, 10, 1000)) : - countRecords(reader); + countRecordsInQueryInterval(reader, new QueryInterval(1, 10, 1000)) : + countRecords(reader); Assert.assertEquals(count, expectedCount); } @@ -512,18 +548,18 @@ public void testSamReaderFromSeekableStream() throws IOException { Assert.assertEquals(countRecords(reader), 10); } - @Test public void testSamReaderFromURL() throws IOException { final String samFilePath = new File(TEST_DATA_DIR, "unsorted.sam").getAbsolutePath(); final URL samURL = new URL("file://" + samFilePath); final SamReaderFactory factory = SamReaderFactory.makeDefault() .validationStringency(ValidationStringency.SILENT); - final SamReader reader = factory.open(SamInputResource.of(samURL)); - Assert.assertEquals(countRecords(reader), 10); + try (final SamReader reader = factory.open(SamInputResource.of(samURL))) { + Assert.assertEquals(countRecords(reader), 10); + } } - @Test(expectedExceptions=SAMFormatException.class) + @Test(expectedExceptions = SAMFormatException.class) public void testSamReaderFromMalformedSeekableStream() throws IOException { // use a bogus (.bai file) to force SamReaderFactory to fall through to the // fallback code that assumes a SAM File when it can't determine the @@ -531,9 +567,62 @@ public void testSamReaderFromMalformedSeekableStream() throws IOException { final File samFile = new File(TEST_DATA_DIR, "cram_with_bai_index.cram.bai"); final SamReaderFactory factory = SamReaderFactory.makeDefault() .validationStringency(ValidationStringency.SILENT); - final SamReader reader = factory.open( - SamInputResource.of(new SeekableFileStream(samFile))); - countRecords(reader); + try (final SamReader reader = factory.open( + SamInputResource.of(new SeekableFileStream(samFile)))) { + countRecords(reader); + } } + @Test(singleThreaded = true, groups = "unix") + public void testWriteAndReadFromPipe() throws IOException, InterruptedException, ExecutionException, TimeoutException { + final SAMRecordSetBuilder builder = new SAMRecordSetBuilder(false, SortOrder.unsorted); + for (int i = 1; i <= 5000; ++i) { + builder.addPair("q" + i, 0, i, i); + } + + for (final boolean usePath : CollectionUtil.makeList(true, false)) { + + final File fifo = File.createTempFile("fifo", ""); + Assert.assertTrue(fifo.delete()); + fifo.deleteOnExit(); + final Process exec = new ProcessBuilder("mkfifo", fifo.getAbsolutePath()).start(); + exec.waitFor(1, TimeUnit.MINUTES); + Assert.assertEquals(exec.exitValue(), 0, "mkfifo failed with exit code " + 0); + + ExecutorService executor = null; + try { + executor = Executors.newSingleThreadExecutor(); + final Future future = executor.submit(() -> { + try (final SAMFileWriter writer = new SAMFileWriterFactory() + .setCreateIndex(false) + .setCreateMd5File(false) + .makeBAMWriter(builder.getHeader(), true, fifo)) { + + int written = 0; + for (final SAMRecord read : builder) { + writer.addAlignment(read); + written += 1; + } + return written; + } + }); + final SamInputResource res = usePath ? + SamInputResource.of(fifo.toPath()) : + SamInputResource.of(fifo); + + int count = 0; + try (final SamReader in = SamReaderFactory.make().open(res)) { + for (final SAMRecord rec : in) { + Assert.assertEquals(rec.getReadName(), "q" + rec.getAlignmentStart()); + count += 1; + } + } + + Assert.assertEquals(count, builder.size()); + Assert.assertEquals(count, future.get().intValue()); + } finally { + if (executor != null) executor.shutdownNow(); + } + } + } } diff --git a/src/test/java/htsjdk/samtools/SamReaderTest.java b/src/test/java/htsjdk/samtools/SamReaderTest.java index 4d4d056343..a2dc9d469c 100644 --- a/src/test/java/htsjdk/samtools/SamReaderTest.java +++ b/src/test/java/htsjdk/samtools/SamReaderTest.java @@ -25,23 +25,29 @@ import htsjdk.HtsjdkTest; import htsjdk.samtools.util.CloseableIterator; -import htsjdk.samtools.util.CloserUtil; +import htsjdk.samtools.util.PeekableIterator; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; public class SamReaderTest extends HtsjdkTest { private static final File TEST_DATA_DIR = new File("src/test/resources/htsjdk/samtools"); @Test(dataProvider = "variousFormatReaderTestCases") - public void variousFormatReaderTest(final String inputFile) { + public void variousFormatReaderTest(final String inputFile) throws IOException { final File input = new File(TEST_DATA_DIR, inputFile); - final SamReader reader = SamReaderFactory.makeDefault().open(input); - for (final SAMRecord rec : reader) { + try(final SamReader reader = SamReaderFactory.makeDefault().open(input)) { + for (final SAMRecord rec : reader) { + //just scan through the lines + } } - CloserUtil.close(reader); } @DataProvider(name = "variousFormatReaderTestCases") @@ -58,18 +64,18 @@ public Object[][] variousFormatReaderTestCases() { // tests for CRAM indexing @Test(dataProvider = "SmallCRAMTest") - public void CRAMIndexTest(final String inputFile, final String referenceFile, QueryInterval queryInterval, String expectedReadName) { + public void CRAMIndexTest(final String inputFile, final String referenceFile, QueryInterval queryInterval, String expectedReadName) throws IOException { final File input = new File(TEST_DATA_DIR, inputFile); final File reference = new File(TEST_DATA_DIR, referenceFile); - final SamReader reader = SamReaderFactory.makeDefault().referenceSequence(reference).open(input); - Assert.assertTrue(reader.hasIndex()); + try(final SamReader reader = SamReaderFactory.makeDefault().referenceSequence(reference).open(input)) { + Assert.assertTrue(reader.hasIndex()); - final CloseableIterator iterator = reader.query(new QueryInterval[]{queryInterval}, false); - Assert.assertTrue(iterator.hasNext()); - SAMRecord r1 = iterator.next(); - Assert.assertEquals(r1.getReadName(), expectedReadName); + final CloseableIterator iterator = reader.query(new QueryInterval[]{queryInterval}, false); + Assert.assertTrue(iterator.hasNext()); + SAMRecord r1 = iterator.next(); + Assert.assertEquals(r1.getReadName(), expectedReadName); - CloserUtil.close(reader); + } } @DataProvider(name = "SmallCRAMTest") @@ -83,12 +89,12 @@ public Object[][] CRAMIndexTestData() { } @Test(dataProvider = "NoIndexCRAMTest") - public void CRAMNoIndexTest(final String inputFile, final String referenceFile) { + public void CRAMNoIndexTest(final String inputFile, final String referenceFile) throws IOException { final File input = new File(TEST_DATA_DIR, inputFile); final File reference = new File(TEST_DATA_DIR, referenceFile); - final SamReader reader = SamReaderFactory.makeDefault().referenceSequence(reference).open(input); - Assert.assertFalse(reader.hasIndex()); - CloserUtil.close(reader); + try(final SamReader reader = SamReaderFactory.makeDefault().referenceSequence(reference).open(input)) { + Assert.assertFalse(reader.hasIndex()); + } } @DataProvider(name = "NoIndexCRAMTest") @@ -113,34 +119,38 @@ public SAMRecord createSAMRecord(final SAMFileHeader header) { @Override public BAMRecord createBAMRecord(final SAMFileHeader header, final int referenceSequenceIndex, final int alignmentStart, final short readNameLength, final short mappingQuality, final int indexingBin, final int cigarLen, final int flags, final int readLen, final int mateReferenceSequenceIndex, final int mateAlignmentStart, final int insertSize, final byte[] variableLengthBlock) { ++bamRecordsCreated; - return super.createBAMRecord(header, referenceSequenceIndex, alignmentStart, readNameLength, mappingQuality, indexingBin, cigarLen, flags, readLen, mateReferenceSequenceIndex, mateAlignmentStart, insertSize, variableLengthBlock); + return super.createBAMRecord(header, referenceSequenceIndex, alignmentStart, readNameLength, mappingQuality, + indexingBin, cigarLen, flags, readLen, mateReferenceSequenceIndex, + mateAlignmentStart, insertSize, variableLengthBlock); } } @Test(dataProvider = "variousFormatReaderTestCases") - public void samRecordFactoryTest(final String inputFile) { + public void samRecordFactoryTest(final String inputFile) throws IOException { final File input = new File(TEST_DATA_DIR, inputFile); final SAMRecordFactoryTester factory = new SAMRecordFactoryTester(); - final SamReader reader = SamReaderFactory.makeDefault().samRecordFactory(factory).open(input); - int i = 0; - for (final SAMRecord rec : reader) { - ++i; + try(final SamReader reader = SamReaderFactory.makeDefault().samRecordFactory(factory).open(input)){ + for (final SAMRecord rec : reader) { + ++i; + } } - CloserUtil.close(reader); Assert.assertTrue(i > 0); - if (inputFile.endsWith(".sam") || inputFile.endsWith(".sam.gz")) Assert.assertEquals(factory.samRecordsCreated, i); - else if (inputFile.endsWith(".bam")) Assert.assertEquals(factory.bamRecordsCreated, i); + if (inputFile.endsWith(".sam") || inputFile.endsWith(".sam.gz")) { + Assert.assertEquals(factory.samRecordsCreated, i); + } else if (inputFile.endsWith(".bam")) { + Assert.assertEquals(factory.bamRecordsCreated, i); + } } - @Test(dataProvider = "cramTestCases", expectedExceptions=IllegalStateException.class) - public void testReferenceRequiredForCRAM(final String inputFile, final String ignoredReferenceFile) { + @Test(dataProvider = "cramTestCases", expectedExceptions = IllegalStateException.class) + public void testReferenceRequiredForCRAM(final String inputFile, final String ignoredReferenceFile) throws IOException { final File input = new File(TEST_DATA_DIR, inputFile); - final SamReader reader = SamReaderFactory.makeDefault().open(input); - for (final SAMRecord rec : reader) { + try(final SamReader reader = SamReaderFactory.makeDefault().open(input)) { + for (final SAMRecord rec : reader) { + } } - CloserUtil.close(reader); } @DataProvider(name = "cramTestCases") @@ -153,13 +163,13 @@ public Object[][] cramTestPositiveCases() { } @Test(dataProvider = "cramTestCases") - public void testIterateCRAMWithIndex(final String inputFile, final String referenceFile) { + public void testIterateCRAMWithIndex(final String inputFile, final String referenceFile) throws IOException { final File input = new File(TEST_DATA_DIR, inputFile); final File reference = new File(TEST_DATA_DIR, referenceFile); - final SamReader reader = SamReaderFactory.makeDefault().referenceSequence(reference).open(input); - for (final SAMRecord rec : reader) { + try(final SamReader reader = SamReaderFactory.makeDefault().referenceSequence(reference).open(input)) { + for (final SAMRecord rec : reader) { + } } - CloserUtil.close(reader); } @Test @@ -169,4 +179,63 @@ public void samRecordFactoryNullHeaderTest() { Assert.assertTrue(samRec.getHeader() == null); } + @Test + public void testAssertingIteratorUsesLenientOrdering() { + // The coordinate comparator's strict sort sorts lower mapping qualities first, + // so this list is not sorted with respect to that comparator, but it is sorted with respect to the more lenient + // file order comparator which only checks the position. + final List looselySorted = Arrays.asList(createRecord(1, 10), + createRecord(1, 1), + createRecord(2, 1)); + + final SAMRecordCoordinateComparator coordinateComparator = new SAMRecordCoordinateComparator(); + + //sanity check that this really sorts differently with the file order comparator vs the full ordering coordinate order comparator + final List sortedWithFileOrderComparator = looselySorted.stream() + .sorted(coordinateComparator::fileOrderCompare) + .collect(Collectors.toList()); + Assert.assertEquals(sortedWithFileOrderComparator, looselySorted); + + final List sortedWithFullOrderComparator = looselySorted.stream() + .sorted(coordinateComparator) + .collect(Collectors.toList()); + + Assert.assertNotEquals(sortedWithFullOrderComparator, looselySorted); + + final SamReader.AssertingIterator iter = new SamReader.AssertingIterator(new PeekableIterator<>(looselySorted.iterator())); + iter.assertSorted(SAMFileHeader.SortOrder.coordinate); + int count = 0; + + while (iter.hasNext()) { + iter.next(); + count++; + } + Assert.assertEquals(count, 3); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testAssertingIteratorCorrectlyFailsWhenOutOfOrder() { + final List unsorted = Arrays.asList(createRecord(10, 1), createRecord(1, 1)); + final SamReader.AssertingIterator iter = new SamReader.AssertingIterator(new PeekableIterator<>(unsorted.iterator())); + iter.assertSorted(SAMFileHeader.SortOrder.coordinate); + + while (iter.hasNext()) { + iter.next(); + } + } + + private static SAMRecord createRecord(int start, int mappingQuality) { + final SAMRecord rec = new SAMRecord(getHeader()); + rec.setReadName("read"); + rec.setReferenceName("1"); + rec.setAlignmentStart(start); + rec.setMappingQuality(mappingQuality); + return rec; + } + + private static SAMFileHeader getHeader() { + final SAMFileHeader header = new SAMFileHeader(); + header.addSequence(new SAMSequenceRecord("1", 1000)); + return header; + } } diff --git a/src/test/java/htsjdk/samtools/SamSpecIntTest.java b/src/test/java/htsjdk/samtools/SamSpecIntTest.java index 2ebc24e701..58dcb79d23 100644 --- a/src/test/java/htsjdk/samtools/SamSpecIntTest.java +++ b/src/test/java/htsjdk/samtools/SamSpecIntTest.java @@ -27,6 +27,7 @@ import htsjdk.HtsjdkTest; import htsjdk.samtools.util.CloserUtil; import org.testng.Assert; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; @@ -35,50 +36,49 @@ import java.util.List; public class SamSpecIntTest extends HtsjdkTest { - private static final File SAM_INPUT = new File("src/test/resources/htsjdk/samtools/inttest.sam"); - private static final File BAM_INPUT = new File("src/test/resources/htsjdk/samtools/inttest.bam"); + private static final File TEST_DATA_DIR = new File("src/test/resources/htsjdk/samtools"); - @Test - public void testSamIntegers() throws IOException { - final List errorMessages = new ArrayList(); - final SamReader samReader = SamReaderFactory.makeDefault().open(SAM_INPUT); - final File bamOutput = File.createTempFile("test", ".bam"); - final File samOutput = File.createTempFile("test", ".sam"); - final SAMFileWriter samWriter = new SAMFileWriterFactory().makeWriter(samReader.getFileHeader(), true, samOutput, null); - final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeWriter(samReader.getFileHeader(), true, bamOutput, null); + @DataProvider(name = "testSamIntegersTestCases") + public Object[][] testSamIntegersTestCases() { + return new Object[][]{ + {"inttest.sam"}, + {"inttest_large_coordinates.sam"} + }; + } - final SAMRecordIterator iterator = samReader.iterator(); - while (iterator.hasNext()) { - try { - final SAMRecord rec = iterator.next(); - samWriter.addAlignment(rec); - bamWriter.addAlignment(rec); - } catch (final Throwable e) { - System.out.println(e.getMessage()); - errorMessages.add(e.getMessage()); - } - } + @DataProvider(name = "testBamIntegersTestCases") + public Object[][] testBamIntegersTestCases() { + return new Object[][]{ + {"inttest.bam"}, + {"inttest_large_coordinates.bam"} + }; + } - CloserUtil.close(samReader); - samWriter.close(); - bamWriter.close(); - Assert.assertEquals(errorMessages.size(), 0); - bamOutput.deleteOnExit(); - samOutput.deleteOnExit(); + @Test(dataProvider = "testSamIntegersTestCases") + public void testSamIntegers(final String inputFile) throws IOException { + final File input = new File(TEST_DATA_DIR, inputFile); + final SamReader samReader = SamReaderFactory.makeDefault().open(input); + + tryToWriteToSamAndBam(samReader); } - @Test - public void testBamIntegers() throws IOException { - final List errorMessages = new ArrayList(); - final SamReader bamReader = SamReaderFactory.makeDefault().open(BAM_INPUT); + @Test(dataProvider = "testBamIntegersTestCases") + public void testBamIntegers(final String inputFile) throws IOException { + final File input = new File(TEST_DATA_DIR, inputFile); + final SamReader bamReader = SamReaderFactory.makeDefault().open(input); + + tryToWriteToSamAndBam(bamReader); + } + + private void tryToWriteToSamAndBam(final SamReader reader) throws IOException { final File bamOutput = File.createTempFile("test", ".bam"); final File samOutput = File.createTempFile("test", ".sam"); - final SAMFileWriter samWriter = new SAMFileWriterFactory().makeWriter(bamReader.getFileHeader(), true, samOutput, null); - final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeWriter(bamReader.getFileHeader(), true, bamOutput, null); - final SAMRecordIterator iterator = bamReader.iterator(); - while (iterator.hasNext()) { + final SAMFileWriter samWriter = new SAMFileWriterFactory().makeWriter(reader.getFileHeader(), true, samOutput, null); + final SAMFileWriter bamWriter = new SAMFileWriterFactory().makeWriter(reader.getFileHeader(), true, bamOutput, null); + + final List errorMessages = new ArrayList<>(); + for (SAMRecord rec : reader) { try { - final SAMRecord rec = iterator.next(); samWriter.addAlignment(rec); bamWriter.addAlignment(rec); } catch (final Throwable e) { @@ -87,7 +87,7 @@ public void testBamIntegers() throws IOException { } } - CloserUtil.close(bamReader); + CloserUtil.close(reader); samWriter.close(); bamWriter.close(); Assert.assertEquals(errorMessages.size(), 0); diff --git a/src/test/java/htsjdk/samtools/TextTagCodecTest.java b/src/test/java/htsjdk/samtools/TextTagCodecTest.java new file mode 100644 index 0000000000..7cedf19f34 --- /dev/null +++ b/src/test/java/htsjdk/samtools/TextTagCodecTest.java @@ -0,0 +1,112 @@ +package htsjdk.samtools; + +import htsjdk.HtsjdkTest; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.Map; + +public class TextTagCodecTest extends HtsjdkTest { + + @DataProvider + public Object[][] getArraysToEncode(){ + return new Object[][]{ + {new byte[0], true, "xa:B:c"}, + {new byte[0], false, "xa:B:C"}, + {new byte[]{1, 2, 3}, true, "xa:B:c,1,2,3"}, + {new byte[]{1, 2, 3}, false, "xa:B:C,1,2,3"}, + + {new short[0], true, "xa:B:s"}, + {new short[0], false, "xa:B:S"}, + {new short[]{1, 2, 3}, true, "xa:B:s,1,2,3"}, + {new short[]{1, 2, 3}, false, "xa:B:S,1,2,3"}, + + {new int[0], true, "xa:B:i"}, + {new int[0], false, "xa:B:I"}, + {new int[]{1, 2, 3}, true, "xa:B:i,1,2,3"}, + {new int[]{1, 2, 3}, false, "xa:B:I,1,2,3"}, + + {new float[0], true, "xa:B:f"}, + {new float[]{1.0f, 2.0f, 3.0f}, true, "xa:B:f,1.0,2.0,3.0"}, + + }; + } + + @Test(dataProvider = "getArraysToEncode") + public void testEmptyAndNonEmptyArrayEncoding(Object array, boolean isSigned, String expectedTag){ + final TextTagCodec textTagCodec = new TextTagCodec(); + final String tagName = "xa"; + final String encodedTag = isSigned + ? textTagCodec.encode(tagName, array) + : textTagCodec.encodeUnsignedArray(tagName, array); + Assert.assertEquals(encodedTag, expectedTag); + } + + @DataProvider + public Object[][] getArraysToDecode(){ + return new Object[][]{ + {"xa:B:c", new byte[0]}, + {"xa:B:C", new TagValueAndUnsignedArrayFlag(new byte[0], true)}, + {"xa:B:c,1,2,3", new byte[]{1, 2, 3}}, + {"xa:B:C,1,2,3", new TagValueAndUnsignedArrayFlag(new byte[]{1, 2, 3}, true)}, + {"xa:B:c,", new byte[0]}, + {"xa:B:C,", new TagValueAndUnsignedArrayFlag(new byte[0], true)}, + + {"xa:B:s", new short[0]}, + {"xa:B:S", new TagValueAndUnsignedArrayFlag(new short[0], true)}, + {"xa:B:s,1,2,3", new short[]{1, 2, 3}}, + {"xa:B:S,1,2,3", new TagValueAndUnsignedArrayFlag(new short[]{1, 2, 3}, true)}, + {"xa:B:s,", new short[0]}, + {"xa:B:S,", new TagValueAndUnsignedArrayFlag(new short[0], true)}, + + {"xa:B:i", new int[0]}, + {"xa:B:I", new TagValueAndUnsignedArrayFlag(new int[0], true)}, + {"xa:B:i,1,2,3", new int[]{1, 2, 3}}, + {"xa:B:I,1,2,3", new TagValueAndUnsignedArrayFlag(new int[]{1, 2, 3}, true)}, + {"xa:B:i,", new int[0]}, + {"xa:B:I,", new TagValueAndUnsignedArrayFlag(new int[0], true)}, + + {"xa:B:f", new float[0]}, + {"xa:B:f,", new float[0]}, + {"xa:B:f,1.0,2.0,3.0", new float[]{1.0f, 2.0f, 3.0f}}, + }; + } + + @Test(dataProvider = "getArraysToDecode") + public void testEmptyAndNonEmptyArrayDecoding(String tag, Object expectedValue) { + final TextTagCodec textTagCodec = new TextTagCodec(); + final Map.Entry decoded = textTagCodec.decode(tag); + + Assert.assertEquals(decoded.getKey(), "xa"); + + final Object value = decoded.getValue(); + if( value instanceof TagValueAndUnsignedArrayFlag){ + Assert.assertTrue(expectedValue instanceof TagValueAndUnsignedArrayFlag); + final TagValueAndUnsignedArrayFlag typedValue = (TagValueAndUnsignedArrayFlag) value; + final TagValueAndUnsignedArrayFlag typedExpected = (TagValueAndUnsignedArrayFlag) expectedValue; + Assert.assertEquals(typedValue.value, typedExpected.value); + Assert.assertEquals(typedValue.isUnsignedArray, typedExpected.isUnsignedArray); + } else { + Assert.assertEquals(value, expectedValue); + } + } + + @DataProvider + public Object[][] getBadArrayTags(){ + return new Object[][]{ + {"xa:B"}, // no colon + {"xa:B:F"}, // there is no such thing as unsigned floating point + {"xa:B:F,1.0,2.0"}, // same as above but empty arrays have a special path + {"xa:B:,1,2,3"}, // missing type + {"xa:B:c,700"}, //out of bounds + {"xa:B:C,-10"}, // negative in unsigned array + }; + } + + @Test(dataProvider = "getBadArrayTags", expectedExceptions = SAMFormatException.class) + public void testBadArrayTags(String badTag){ + final TextTagCodec textTagCodec = new TextTagCodec(); + textTagCodec.decode(badTag); + } +} \ No newline at end of file diff --git a/src/test/java/htsjdk/samtools/ValidateSamFileTest.java b/src/test/java/htsjdk/samtools/ValidateSamFileTest.java index 7602f05464..190a6d5073 100644 --- a/src/test/java/htsjdk/samtools/ValidateSamFileTest.java +++ b/src/test/java/htsjdk/samtools/ValidateSamFileTest.java @@ -420,6 +420,16 @@ public void testCigarOffEndOfReferenceValidation() throws Exception { Assert.assertNotNull(results.get(SAMValidationError.Type.CIGAR_MAPS_OFF_REFERENCE.getHistogramString())); Assert.assertEquals(results.get(SAMValidationError.Type.CIGAR_MAPS_OFF_REFERENCE.getHistogramString()).getValue(), 1.0); } + + @Test + public void testCigarNoSeqValidation() throws Exception { + final SAMRecordSetBuilder samBuilder = new SAMRecordSetBuilder(); + samBuilder.addFrag("name", 0, 1, false); + samBuilder.iterator().next().setReadBases(SAMRecord.NULL_SEQUENCE); + samBuilder.iterator().next().setBaseQualities(SAMRecord.NULL_SEQUENCE); + final Histogram results = executeValidation(samBuilder.getSamReader(), null, IndexValidationStringency.EXHAUSTIVE); + Assert.assertNull(results.get(SAMValidationError.Type.MISMATCH_CIGAR_SEQ_LENGTH .getHistogramString())); + } @Test(expectedExceptions = SAMFormatException.class) public void testConflictingTags() throws Exception { @@ -552,12 +562,6 @@ public Object[][] tagCorrectlyProcessData() throws IOException { "@RG\tID:0\tSM:Hi,Mom!\n" + "E\t147\tchr1\t15\t255\t10M\t=\t2\t-30\tCAACAGAAGC\t)'.*.+2,))\tU2:Z:CAA"; - final String SOTagCorrectlyProcessTestData = - "@HD\tVN:1.0\tSO:NOTKNOWN\n" + - "@SQ\tSN:chr1\tLN:101\n" + - "@RG\tID:0\tSM:Hi,Mom!\n" + - "E\t147\tchr1\t15\t255\t10M\t=\t2\t-30\tCAACAGAAGC\t)'.*.+2,))\tU2:Z:CAA"; - final String GOTagCorrectlyProcessTestData = "@HD\tVN:1.0\tGO:NOTKNOWN\n" + "@SQ\tSN:chr1\tLN:101\n" + @@ -568,7 +572,6 @@ public Object[][] tagCorrectlyProcessData() throws IOException { {E2TagCorrectlyProcessTestData.getBytes(), SAMValidationError.Type.E2_BASE_EQUALS_PRIMARY_BASE}, {E2TagCorrectlyProcessTestData.getBytes(), SAMValidationError.Type.MISMATCH_READ_LENGTH_AND_E2_LENGTH}, {U2TagCorrectlyProcessTestData.getBytes(), SAMValidationError.Type.MISMATCH_READ_LENGTH_AND_U2_LENGTH}, - {SOTagCorrectlyProcessTestData.getBytes(), SAMValidationError.Type.HEADER_TAG_NON_CONFORMING_VALUE}, {GOTagCorrectlyProcessTestData.getBytes(), SAMValidationError.Type.HEADER_TAG_NON_CONFORMING_VALUE} }; } diff --git a/src/test/java/htsjdk/samtools/cram/VersionTest.java b/src/test/java/htsjdk/samtools/cram/VersionTest.java index be2851eb6d..c4b27d89b1 100644 --- a/src/test/java/htsjdk/samtools/cram/VersionTest.java +++ b/src/test/java/htsjdk/samtools/cram/VersionTest.java @@ -91,7 +91,7 @@ public void test_V3() throws IOException { CRC32 digester = new CRC32(); digester.update(containerHeaderBytes); Assert.assertEquals(container.checksum, (int) digester.getValue()); - Assert.assertEquals(CramInt.int32(crcBytes), container.checksum); + Assert.assertEquals(CramInt.readInt32(crcBytes), container.checksum); // test block's crc: cramSeekableStream.seek(firstBlockStart); @@ -102,6 +102,6 @@ public void test_V3() throws IOException { crcBytes = InputStreamUtils.readFully(cramSeekableStream, crcByteSize); digester = new CRC32(); digester.update(blockBytes); - Assert.assertEquals(CramInt.int32(crcBytes), (int) digester.getValue()); + Assert.assertEquals(CramInt.readInt32(crcBytes), (int) digester.getValue()); } } diff --git a/src/test/java/htsjdk/samtools/cram/encoding/BetaIntegerCodecTest.java b/src/test/java/htsjdk/samtools/cram/encoding/BetaIntegerCodecTest.java new file mode 100644 index 0000000000..742da5d81c --- /dev/null +++ b/src/test/java/htsjdk/samtools/cram/encoding/BetaIntegerCodecTest.java @@ -0,0 +1,140 @@ +package htsjdk.samtools.cram.encoding; + +import htsjdk.HtsjdkTest; +import htsjdk.samtools.cram.io.BitOutputStream; +import htsjdk.samtools.cram.io.DefaultBitInputStream; +import htsjdk.samtools.cram.io.DefaultBitOutputStream; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.*; + +public class BetaIntegerCodecTest extends HtsjdkTest { + + private void testCodec(int offset, int bitsPerValue, int[] values) throws IOException { + BitCodec codec = new BetaIntegerCodec(offset, bitsPerValue); + + try (ByteArrayOutputStream os = new ByteArrayOutputStream(); + BitOutputStream bos = new DefaultBitOutputStream(os)) { + + for (int value : values) { + codec.write(bos, value); + } + + int[] actual = new int[values.length]; + try (InputStream is = new ByteArrayInputStream(os.toByteArray()); + DefaultBitInputStream dbis = new DefaultBitInputStream(is)) { + + for (int i = 0; i < values.length; i++) { + actual[i] = codec.read(dbis); + } + } + + Assert.assertEquals(actual, values); + } + } + + // test that the offsets enable the data series to be stored in N bits + + @DataProvider(name = "basicTest") + public Object[][] basicTestData() { + return new Object[][] { + {8, -100, new int[]{100, 101, 102, (1<<8) + 98, (1<<8) + 99}}, + {4, 10015, new int[]{-10015, -10014, -10001, -10000}}, + }; + } + + @Test(dataProvider = "basicTest") + public void basicTest(int bitsPerValue, int offset, int[] values) throws IOException { + testCodec(offset, bitsPerValue, values); + } + + // test that values fit into N bits without offsets + + @DataProvider(name = "basicTestNoOffset") + public Object[][] basicTestNoOffsetData() { + return new Object[][] { + {8, new int[]{0, 1, 2, 100, (1 << 8) - 2, (1 << 8) - 1}}, + {16, new int[]{0, 1, 255, (1 << 16) - 2, (1 << 16) - 1}}, + }; + } + + @Test(dataProvider = "basicTestNoOffset") + public void basicTestNoOffset(int bitsPerValue, int[] values) throws IOException { + testCodec(0, bitsPerValue, values); + } + + // sanity checks for bitsPerValue. Must be > 0 and <= 32 + + @DataProvider(name = "bitsPerValue") + public Object[][] bitsPerValueData() { + return new Object[][] { + {0}, + {-1}, + {33} + }; + } + + @Test(dataProvider = "bitsPerValue", expectedExceptions = IllegalArgumentException.class) + public void bitsPerValue(int bitsPerValue) { + new BetaIntegerCodec(0, bitsPerValue); + } + + // throw Exceptions when offsets + values are too big to store in N bits + + @DataProvider(name = "overflow") + public Object[][] overflowData() { + // tuples of bitsPerValue and offsets + values which are too big to store + return new Object[][] { + // first with zero offset + {1, 0, (1 << 1)}, + {2, 0, (1 << 2)}, + {4, 0, (1 << 4)}, + {8, 0, (1 << 8)}, + {16, 0, (1 << 16)}, + + // adding offset of 1 will put it over + {1, 1, (1 << 1) - 1}, + {2, 1, (1 << 2) - 1}, + {4, 1, (1 << 4) - 1}, + {8, 1, (1 << 8) - 1}, + {16, 1, (1 << 16) - 1}, + }; + } + + @Test(dataProvider = "overflow", expectedExceptions = IllegalArgumentException.class) + public void overflow(int bitsPerValue, int offset, int value) throws IOException { + BitCodec codec = new BetaIntegerCodec(offset, bitsPerValue); + + try (ByteArrayOutputStream os = new ByteArrayOutputStream(); + BitOutputStream bos = new DefaultBitOutputStream(os)) { + codec.write(bos, value); + } + } + + // throw Exceptions when offsets + values are negative + + @DataProvider(name = "negativeTest") + public Object[][] negativeTestData() { + // tuples of bitsPerValue and offsets + values which are negative + return new Object[][] { + {1, 0, -1}, + {1, -1, 0}, + {2, 0, -1}, + {2, -1, 0}, + {8, -100, 99}, + {8, 99, -100}, + }; + } + + @Test(dataProvider = "negativeTest", expectedExceptions = IllegalArgumentException.class) + public void negativeTest(int bitsPerValue, int offset, int value) throws IOException { + BitCodec codec = new BetaIntegerCodec(offset, bitsPerValue); + + try (ByteArrayOutputStream os = new ByteArrayOutputStream(); + BitOutputStream bos = new DefaultBitOutputStream(os)) { + codec.write(bos, value); + } + } +} \ No newline at end of file diff --git a/src/test/java/htsjdk/samtools/cram/io/CramIntArrayTest.java b/src/test/java/htsjdk/samtools/cram/io/CramIntArrayTest.java new file mode 100644 index 0000000000..22f5b5dc2a --- /dev/null +++ b/src/test/java/htsjdk/samtools/cram/io/CramIntArrayTest.java @@ -0,0 +1,27 @@ +package htsjdk.samtools.cram.io; + +import htsjdk.HtsjdkTest; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; + +public class CramIntArrayTest extends HtsjdkTest { + + @Test(dataProvider = "testInt32Arrays", dataProviderClass = IOTestCases.class) + public void runTest(List ints) throws IOException { + + int[] inputArray = ints.stream().mapToInt(Integer::intValue).toArray(); + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + CramIntArray.write(inputArray, baos); + + try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) { + int[] outputArray = CramIntArray.array(bais); + Assert.assertEquals(inputArray, outputArray, "Arrays did not match"); + } + } + } +} diff --git a/src/test/java/htsjdk/samtools/cram/io/CramIntTest.java b/src/test/java/htsjdk/samtools/cram/io/CramIntTest.java new file mode 100644 index 0000000000..7e3c2de67a --- /dev/null +++ b/src/test/java/htsjdk/samtools/cram/io/CramIntTest.java @@ -0,0 +1,106 @@ +package htsjdk.samtools.cram.io; + +import htsjdk.HtsjdkTest; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +public class CramIntTest extends HtsjdkTest { + private byte[] streamWritten(List ints) throws IOException { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + for (int value : ints) { + CramInt.writeInt32(value, baos); + } + return baos.toByteArray(); + } + } + + private byte[] byteArrayWritten(List ints) { + final int bufSize = 4; + final int arraySize = bufSize * ints.size(); + byte[] array = new byte[arraySize]; + + int offset = 0; + byte[] arrayBuffer; + + for (int value : ints) { + arrayBuffer = CramInt.writeInt32(value); + System.arraycopy(arrayBuffer, 0, array, offset, bufSize); + offset += bufSize; + } + + return array; + } + + @Test(dataProvider = "littleEndianTests32", dataProviderClass = IOTestCases.class) + public void checkStreamLittleEndian(Integer testInt, byte[] expected) throws IOException { + List ints = new ArrayList<>(); + ints.add(testInt); + + byte[] actual = streamWritten(ints); + Assert.assertEquals(actual, expected); + } + + @Test(dataProvider = "littleEndianTests32", dataProviderClass = IOTestCases.class) + public void checkByteArrayLittleEndian(Integer testInt, byte[] expected) { + List ints = new ArrayList<>(); + ints.add(testInt); + + byte[] actual = byteArrayWritten(ints); + Assert.assertEquals(actual, expected); + } + + // Combinatorial tests of 2 CramInt write methods x 3 CramInt read methods + + @Test(dataProvider = "testInt32Arrays", dataProviderClass = IOTestCases.class) + public void matchStreamRead(List ints) throws IOException { + byte[][] inputs = {streamWritten(ints), byteArrayWritten(ints)}; + + for (byte[] byteArray : inputs) { + try (ByteArrayInputStream bais = new ByteArrayInputStream(byteArray)) { + for (int value : ints) { + int fromStream = CramInt.readInt32(bais); + Assert.assertEquals(fromStream, value, "Value did not match"); + } + } + } + } + + @Test(dataProvider = "testInt32Arrays", dataProviderClass = IOTestCases.class) + public void matchBufferRead(List ints) throws IOException { + byte[][] inputs = {streamWritten(ints), byteArrayWritten(ints)}; + + for (byte[] byteArray : inputs) { + ByteBuffer bb = ByteBuffer.wrap(byteArray); + + for (int value : ints) { + int fromBuffer = CramInt.readInt32(bb); + Assert.assertEquals(fromBuffer, value, "Value did not match"); + } + } + } + + @Test(dataProvider = "testInt32Arrays", dataProviderClass = IOTestCases.class) + public void matchByteArrayRead(List ints) throws IOException { + byte[][] inputs = {streamWritten(ints), byteArrayWritten(ints)}; + + for (byte[] inputArray : inputs) { + final int bufSize = 4; + byte[] outBuf = new byte[bufSize]; + int offset = 0; + + for (int value : ints) { + System.arraycopy(inputArray, offset, outBuf, 0, bufSize); + int fromBuffer = CramInt.readInt32(outBuf); + Assert.assertEquals(fromBuffer, value, "Value did not match"); + offset += bufSize; + } + } + } +} diff --git a/src/test/java/htsjdk/samtools/cram/io/ExternalCompressionTest.java b/src/test/java/htsjdk/samtools/cram/io/ExternalCompressionTest.java new file mode 100644 index 0000000000..7ee63e3c76 --- /dev/null +++ b/src/test/java/htsjdk/samtools/cram/io/ExternalCompressionTest.java @@ -0,0 +1,54 @@ +package htsjdk.samtools.cram.io; + +import htsjdk.HtsjdkTest; +import htsjdk.samtools.cram.encoding.rans.RANS; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class ExternalCompressionTest extends HtsjdkTest { + public static final File BZIP2_FILE = new File("src/test/resources/htsjdk/samtools/cram/io/bzip2-test.bz2"); + public static final byte[] TEST_BYTES = "This is a simple string to test compression".getBytes(); + + @Test + public void testBZip2Decompression() throws IOException { + final byte [] input = Files.readAllBytes(BZIP2_FILE.toPath()); + final byte [] output = ExternalCompression.unbzip2(input); + Assert.assertEquals(output, "BZip2 worked".getBytes()); + } + + @Test + public void testGZipRoundtrip() throws IOException { + final byte [] compressed = ExternalCompression.gzip(TEST_BYTES); + final byte [] restored = ExternalCompression.gunzip(compressed); + Assert.assertEquals(TEST_BYTES, restored); + } + + @Test + public void testBZip2Roundtrip() throws IOException { + final byte [] compressed = ExternalCompression.bzip2(TEST_BYTES); + final byte [] restored = ExternalCompression.unbzip2(compressed); + Assert.assertEquals(TEST_BYTES, restored); + } + + @Test + public void testRANSRoundtrip() { + for(RANS.ORDER order : RANS.ORDER.values()) { + final byte[] compressed = ExternalCompression.rans(TEST_BYTES, order); + final byte[] restored = ExternalCompression.unrans(compressed); + Assert.assertEquals(TEST_BYTES, restored); + } + } + + @Test + public void testXZRoundtrip() throws IOException { + final byte [] compressed = ExternalCompression.xz(TEST_BYTES); + final byte [] restored = ExternalCompression.unxz(compressed); + Assert.assertEquals(TEST_BYTES, restored); + } + + +} diff --git a/src/test/java/htsjdk/samtools/cram/io/IOTestCases.java b/src/test/java/htsjdk/samtools/cram/io/IOTestCases.java new file mode 100644 index 0000000000..e2a3b88b61 --- /dev/null +++ b/src/test/java/htsjdk/samtools/cram/io/IOTestCases.java @@ -0,0 +1,135 @@ +package htsjdk.samtools.cram.io; + +import htsjdk.HtsjdkTest; +import org.testng.annotations.DataProvider; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class IOTestCases extends HtsjdkTest { + + @DataProvider(name = "littleEndianTests32") + public static Object[][] littleEndianTests32() { + return new Object[][] { + {1, new byte[]{1, 0, 0, 0}}, // 0x01 + {127, new byte[]{127, 0, 0, 0}}, // 0x7F + {128, new byte[]{-128, 0, 0, 0}}, // 0x80 + {129, new byte[]{-127, 0, 0, 0}}, // 0x81 + {255, new byte[]{-1, 0, 0, 0}}, // 0xFF + {256, new byte[]{0, 1, 0, 0}}, // 0x0100 + {257, new byte[]{1, 1, 0, 0}}, // 0x0101 + {65535, new byte[]{-1, -1, 0, 0}}, // 0xFFFF + {65536, new byte[]{0, 0, 1, 0}}, // 0x010000 + {16777216, new byte[]{0, 0, 0, 1}}, // 0x01000000 + {2147483647, new byte[]{-1, -1, -1, 127}}, // 0x7FFFFFFF + {-2147483648, new byte[]{0, 0, 0, -128}}, // 0x80000000 + {-1, new byte[]{-1, -1, -1, -1}} // 0xFFFFFFFF + }; + } + + private static Object[][] asDataProvider(List list) { + Object[][] params = new Object[list.size()][]; + for (int i = 0; i < params.length; i++) + params[i] = new Object[]{list.get(i)}; + return params; + } + + static List int32Tests() { + List list = new ArrayList(); + + // basics: + list.add(0); + list.add(1); + list.add(127); + list.add(128); + list.add(255); + list.add(256); + list.add(-1); + + // scan with bits: + for (int i = 0; i <= 32; i++) { + list.add((1 << i) - 2); + list.add((1 << i) - 1); + list.add(1 << i); + list.add((1 << i) + 1); + list.add((1 << i) + 1); + } + + // special cases: + list.add(Integer.MAX_VALUE); + list.add(Integer.MIN_VALUE); + list.add(268435456); + + return list; + } + + @DataProvider(name = "testInt32") + public static Object[][] testInt32() { + return asDataProvider(IOTestCases.int32Tests()); + } + + @DataProvider(name = "testInt32Arrays") + public static Object[][] testValues32() { + List int32Tests = IOTestCases.int32Tests(); + List shuffled = new ArrayList<>(int32Tests); + Collections.shuffle(shuffled); + + return new Object[][]{ + {int32Tests}, + {shuffled} + }; + } + + static List int64Tests() { + List list = new ArrayList() ; + + // basics: + list.add(0L); + list.add(0L); + list.add(1L); + list.add(127L); + list.add(128L); + list.add(255L); + list.add(256L); + + // scan with bits: + for (int i = 0; i <= 64; i++) { + list.add((1L << i) - 2); + list.add((1L << i) - 1); + list.add(1L << i); + list.add((1L << i) + 1); + list.add((1L << i) + 1); + } + + // special cases: + list.add(Long.MAX_VALUE); + list.add(Long.MIN_VALUE); + list.add(1125899906842622L) ; + list.add(1125899906842622L); + list.add(562949953421312L); + list.add(4294967296L); + list.add(268435456L); + list.add(2147483648L); + list.add(-1L); + + return list; + } + + @DataProvider(name = "testInt64") + public static Object[][] testInt64() { + return asDataProvider(IOTestCases.int64Tests()); + } + + @DataProvider(name = "testInt64Arrays") + public static Object[][] testValues64() { + List int64Tests = IOTestCases.int64Tests(); + List shuffled = new ArrayList<>(int64Tests); + Collections.shuffle(shuffled); + + return new Object[][]{ + {int64Tests}, + {shuffled} + }; + } +} diff --git a/src/test/java/htsjdk/samtools/cram/io/ITF8Test.java b/src/test/java/htsjdk/samtools/cram/io/ITF8Test.java index a206ad1f04..749d0451bb 100644 --- a/src/test/java/htsjdk/samtools/cram/io/ITF8Test.java +++ b/src/test/java/htsjdk/samtools/cram/io/ITF8Test.java @@ -11,7 +11,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -34,41 +33,7 @@ public void reset() { testBAIS.reset(); } - - @DataProvider(name = "testITF8") - public static Object[][] testValues() { - List list = new ArrayList() ; - - // basics: - list.add(0); - list.add(1); - list.add(127); - list.add(128); - list.add(255); - list.add(256); - list.add(-1); - - // scan with bits: - for (int i = 0; i <= 32; i++) { - list.add((1 << i) - 2); - list.add((1 << i) - 1); - list.add(1 << i); - list.add((1 << i) + 1); - list.add((1 << i) + 1); - } - - // special cases: - list.add(Integer.MAX_VALUE) ; - list.add(Integer.MIN_VALUE); - list.add(268435456); - - Object[][] params = new Object[list.size()][] ; - for (int i=0; i list = new ArrayList() ; - - // basics: - list.add(0L); - list.add(0L); - list.add(1L); - list.add(127L); - list.add(128L); - list.add(255L); - list.add(256L); - - // scan with bits: - for (int i = 0; i <= 64; i++) { - list.add((1L << i) - 2); - list.add((1L << i) - 1); - list.add(1L << i); - list.add((1L << i) + 1); - list.add((1L << i) + 1); - } - - // special cases: - list.add(1125899906842622L) ; - list.add(1125899906842622L); - list.add(562949953421312L); - list.add(4294967296L); - list.add(268435456L); - list.add(2147483648L); - list.add(-1L); - - Object[][] params = new Object[list.size()][] ; - for (int i=0; i" + chr1); + final String sequence = "ACGTACGT"; + writer.println(sequence); + writer.println(sequence + " \t"); + writer.close(); + try (SeekableStream seekableStream = new SeekableFileStream(fasta)) { + final FastaSequenceFile fastaReader = new FastaSequenceFile(fasta.getAbsolutePath(), seekableStream, null, true); + final ReferenceSequence referenceSequence1 = fastaReader.nextSequence(); + Assert.assertEquals(referenceSequence1.getName(), chr1); + Assert.assertEquals(StringUtil.bytesToString(referenceSequence1.getBases()), sequence + sequence); + // try to reset and re-read the first sequence + fastaReader.reset(); + final ReferenceSequence referenceSequence2 = fastaReader.nextSequence(); + Assert.assertEquals(referenceSequence2.getName(), chr1); + Assert.assertEquals(StringUtil.bytesToString(referenceSequence2.getBases()), sequence + sequence); + } + } } diff --git a/src/test/java/htsjdk/samtools/reference/FastaSequenceIndexTest.java b/src/test/java/htsjdk/samtools/reference/FastaSequenceIndexTest.java index c6fa1384ac..e2aa0acf29 100644 --- a/src/test/java/htsjdk/samtools/reference/FastaSequenceIndexTest.java +++ b/src/test/java/htsjdk/samtools/reference/FastaSequenceIndexTest.java @@ -32,6 +32,7 @@ import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.nio.file.Files; @@ -51,7 +52,9 @@ public Object[][] provideHomoSapiens() throws FileNotFoundException { final File sequenceIndexFile = new File(TEST_DATA_DIR,"Homo_sapiens_assembly18.fasta.fai"); return new Object[][] { new Object[] { new FastaSequenceIndex(sequenceIndexFile) }, - { new FastaSequenceIndex(sequenceIndexFile.toPath()) } }; + { new FastaSequenceIndex(sequenceIndexFile.toPath()) }, + { new FastaSequenceIndex(new FileInputStream(sequenceIndexFile)) } + }; } @DataProvider(name="specialcharacters") @@ -59,7 +62,9 @@ public Object[][] provideSpecialCharacters() throws FileNotFoundException { final File sequenceIndexFile = new File(TEST_DATA_DIR,"testing.fai"); return new Object[][] { new Object[] { new FastaSequenceIndex(sequenceIndexFile) }, - { new FastaSequenceIndex(sequenceIndexFile.toPath()) } }; + { new FastaSequenceIndex(sequenceIndexFile.toPath()) }, + { new FastaSequenceIndex(new FileInputStream(sequenceIndexFile)) } + }; } @Test(dataProvider="homosapiens") diff --git a/src/test/java/htsjdk/samtools/reference/ReferenceSequenceFileFactoryTests.java b/src/test/java/htsjdk/samtools/reference/ReferenceSequenceFileFactoryTests.java index 5d827f8904..56921750f6 100644 --- a/src/test/java/htsjdk/samtools/reference/ReferenceSequenceFileFactoryTests.java +++ b/src/test/java/htsjdk/samtools/reference/ReferenceSequenceFileFactoryTests.java @@ -12,6 +12,7 @@ */ public class ReferenceSequenceFileFactoryTests extends HtsjdkTest { public static final File hg18 = new File("src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.fasta"); + public static final File hg18bgzip = new File("src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.fasta.gz"); @Test public void testPositivePath() { final ReferenceSequenceFile f = ReferenceSequenceFileFactory.getReferenceSequenceFile(hg18); @@ -38,6 +39,26 @@ public class ReferenceSequenceFileFactoryTests extends HtsjdkTest { Assert.assertTrue(f instanceof IndexedFastaSequenceFile, "Got non-indexed reader by default."); } + @Test public void testBlockCompressedIndexed() { + final ReferenceSequenceFile f = ReferenceSequenceFileFactory.getReferenceSequenceFile(hg18bgzip, true); + Assert.assertTrue(f instanceof BlockCompressedIndexedFastaSequenceFile); + } + + @DataProvider + public Object[][] canCreateIndexedFastaParams() { + return new Object[][] { + {hg18, true}, + {hg18bgzip, true}, + {new File("src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.noindex.fasta"), false}, + {new File("src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.noindex.fasta.gz"), false}, + {new File("src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.nogzindex.fasta.gz"), false} + }; + } + + @Test(dataProvider = "canCreateIndexedFastaParams") + public void testCanCreateIndexedFastaReader(final File path, final boolean indexed) { + Assert.assertEquals(ReferenceSequenceFileFactory.canCreateIndexedFastaReader(path.toPath()), indexed); + } @DataProvider public Object[][] fastaNames() { diff --git a/src/test/java/htsjdk/samtools/reference/SamLocusAndReferenceIteratorTest.java b/src/test/java/htsjdk/samtools/reference/SamLocusAndReferenceIteratorTest.java new file mode 100644 index 0000000000..badd107d95 --- /dev/null +++ b/src/test/java/htsjdk/samtools/reference/SamLocusAndReferenceIteratorTest.java @@ -0,0 +1,56 @@ +package htsjdk.samtools.reference; + +import htsjdk.HtsjdkTest; +import htsjdk.samtools.SamReader; +import htsjdk.samtools.SamReaderFactory; +import htsjdk.samtools.util.*; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.File; + +public class SamLocusAndReferenceIteratorTest extends HtsjdkTest { + static private final File TEST_DATA_DIR = new File("src/test/resources/htsjdk/samtools/reference"); + + @Test + public void testSamLocusAndReferenceIterator() { + + final File reference = new File(TEST_DATA_DIR, "Homo_sapiens_assembly18.trimmed.fasta"); + final File samFile = new File(TEST_DATA_DIR, "simpleSmallFile.sam"); + final ReferenceSequenceFile referenceSequenceFile = new FastaSequenceFile(reference, false); + final ReferenceSequenceFileWalker referenceSequenceFileWalker = new ReferenceSequenceFileWalker(referenceSequenceFile); + + final SamReader samReader = SamReaderFactory.makeDefault().open(samFile); + final SamLocusIterator samLocusIterator = new SamLocusIterator(samReader); + final SamLocusAndReferenceIterator samLocusAndReferences = new SamLocusAndReferenceIterator(referenceSequenceFileWalker, samLocusIterator); + + IntervalList intervalList = new IntervalList(samReader.getFileHeader()); + intervalList.add(new Interval("chrM", 1, 36)); + intervalList.add(new Interval("chr20", 8401, 8460)); + + OverlapDetector overlapDetector = new OverlapDetector<>(0, 0); + overlapDetector.addAll(intervalList.getIntervals(), intervalList.getIntervals()); + + for (final SamLocusAndReferenceIterator.SAMLocusAndReference samLocusAndReference : samLocusAndReferences) { + // The sam file only has coverage in the intervals that are within 'intervalList', and there the coverage should + // be exactly 2 since there are two overlapping, paired reads. This is what this test is testing: + Assert.assertEquals(samLocusAndReference.getRecordAndOffsets().size(), overlapDetector.overlapsAny(samLocusAndReference.getLocus()) ? 2 : 0, "Position:" + samLocusAndReference.getLocus().toString()); + + // all the reads are equal to the reference...this is what this test is testing. + for (final SamLocusIterator.RecordAndOffset recordAndOffset : samLocusAndReference.getRecordAndOffsets()) + Assert.assertTrue(SequenceUtil.basesEqual(samLocusAndReference.getReferenceBase(), recordAndOffset.getReadBase()), "Record: " + recordAndOffset.getRecord() + " Position:" + samLocusAndReference.getLocus().toString()); + } + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testSamLocusAndReferenceIteratorMismatch() { + final File reference = new File(TEST_DATA_DIR, "reference_with_trailing_whitespace.fasta"); + final File samFile = new File(TEST_DATA_DIR, "simpleSmallFile.sam"); + final ReferenceSequenceFile referenceSequenceFile = new FastaSequenceFile(reference, false); + final ReferenceSequenceFileWalker referenceSequenceFileWalker = new ReferenceSequenceFileWalker(referenceSequenceFile); + + final SamReader samReader = SamReaderFactory.makeDefault().open(samFile); + final SamLocusIterator samLocusIterator = new SamLocusIterator(samReader); + final SamLocusAndReferenceIterator shouldThrow = new SamLocusAndReferenceIterator(referenceSequenceFileWalker, samLocusIterator); + } +} diff --git a/src/test/java/htsjdk/samtools/seekablestream/SeekableBufferedStreamTest.java b/src/test/java/htsjdk/samtools/seekablestream/SeekableBufferedStreamTest.java index 8de587327a..4e498828db 100644 --- a/src/test/java/htsjdk/samtools/seekablestream/SeekableBufferedStreamTest.java +++ b/src/test/java/htsjdk/samtools/seekablestream/SeekableBufferedStreamTest.java @@ -29,6 +29,7 @@ import org.testng.annotations.Test; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; @@ -68,6 +69,20 @@ public void testRandomRead() throws IOException { assertEquals(buffer1, buffer2); } + @Test + public void testReadExactlyOneByteAtEndOfFile() throws IOException { + try (final SeekableStream stream = new SeekableHTTPStream(new URL(BAM_URL_STRING))){ + byte[] buff = new byte[1]; + long length = stream.length(); + stream.seek(length - 1); + Assert.assertFalse(stream.eof()); + Assert.assertEquals(stream.read(buff), 1); + Assert.assertTrue(stream.eof()); + Assert.assertEquals(stream.read(buff), -1); + } + } + + /** * Test an attempt to read past the end of the file. The test file is 594,149 bytes in length. The test * attempts to read a 1000 byte block starting at position 594000. A correct result would return 149 bytes. @@ -123,6 +138,65 @@ public void testSkip() throws IOException { } } + @Test + public void testSeek() throws IOException { + final int bufferSize = 20000; + final int filledBufferSize = bufferSize / 2; + final int startPosition = 250000; + final int length = 5000; + + class LimitedSeekableFileStream extends SeekableFileStream { + LimitedSeekableFileStream(File file) throws FileNotFoundException { + super(file); + } + @Override + public int read(byte[] buffer, int offset, int length) throws IOException { + // only return a fraction of the buffer size (this is allowed by the read contract) to ensure that + // BufferedInputStream's internal buffer is not filled, and so some of its contents are not valid + return super.read(buffer, offset, Math.min(length, filledBufferSize)); + } + } + + final int[] RELATIVE_SEEK_OFFSET = new int[]{-bufferSize*2, -bufferSize, -bufferSize/2, -length, -length/2, -1, + 0, 1, length/2, length, bufferSize/2, bufferSize-1, bufferSize, bufferSize*2}; + + for (final int seekOffset : RELATIVE_SEEK_OFFSET) { + try (SeekableStream unBufferedStream = new SeekableFileStream(BAM_FILE); + SeekableBufferedStream bufferedStream = new SeekableBufferedStream(new LimitedSeekableFileStream(BAM_FILE), bufferSize)) { + byte[] buffer1 = new byte[length]; + unBufferedStream.seek(startPosition); + int bytesRead = unBufferedStream.read(buffer1, 0, length); + Assert.assertEquals(length, bytesRead); + + byte[] buffer2 = new byte[length]; + bufferedStream.seek(startPosition); + bytesRead = bufferedStream.read(buffer2, 0, length); + Assert.assertEquals(length, bytesRead); + + Assert.assertEquals(buffer1, buffer2); + + unBufferedStream.seek(startPosition + seekOffset); + bytesRead = unBufferedStream.read(buffer1, 0, length); + Assert.assertEquals(length, bytesRead); + + Object internalBuffer = bufferedStream.bufferedStream; + bufferedStream.seek(startPosition + seekOffset); + bytesRead = bufferedStream.read(buffer2, 0, length); + Assert.assertEquals(length, bytesRead); + Object newInternalBuffer = bufferedStream.bufferedStream; + if (seekOffset >=0 && seekOffset < filledBufferSize) { + Assert.assertSame(internalBuffer, newInternalBuffer, + "Internal buffer should have been reused for seek offset " + seekOffset); + } else { + Assert.assertNotSame(internalBuffer, newInternalBuffer, + "Internal buffer should not have been reused for seek offset " + seekOffset); + } + + Assert.assertEquals(buffer1, buffer2, "Error at relative seek offset " + seekOffset); + } + } + } + private int reallyRead(final byte[] bytes, final SeekableBufferedStream in) throws IOException { int read = 0, total = 0; do { diff --git a/src/test/java/htsjdk/samtools/seekablestream/SeekableFTPStreamTest.java b/src/test/java/htsjdk/samtools/seekablestream/SeekableFTPStreamTest.java index 4dfc8b78b6..81105ab467 100644 --- a/src/test/java/htsjdk/samtools/seekablestream/SeekableFTPStreamTest.java +++ b/src/test/java/htsjdk/samtools/seekablestream/SeekableFTPStreamTest.java @@ -36,6 +36,7 @@ * @author Jim Robinson * @since 10/3/11 */ +@Test(groups = "ftp") public class SeekableFTPStreamTest extends HtsjdkTest { @@ -44,13 +45,13 @@ public class SeekableFTPStreamTest extends HtsjdkTest { static byte[] expectedBytes = "abcdefghijklmnopqrstuvwxyz\n".getBytes(); SeekableFTPStream stream; - @BeforeMethod + @BeforeMethod() public void setUp() throws IOException { stream = new SeekableFTPStream(new URL(urlString)); } - @AfterMethod + @AfterMethod() public void tearDown() throws IOException { stream.close(); } diff --git a/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamGZIPinputStreamIntegrationTest.java b/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamGZIPinputStreamIntegrationTest.java new file mode 100644 index 0000000000..6ef70f08e1 --- /dev/null +++ b/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamGZIPinputStreamIntegrationTest.java @@ -0,0 +1,145 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Daniel Gomez-Sanchez + * + * 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.seekablestream; + +import htsjdk.HtsjdkTest; +import htsjdk.samtools.util.BlockCompressedInputStream; +import htsjdk.samtools.util.BufferedLineReader; +import htsjdk.samtools.util.LineReader; +import htsjdk.samtools.util.TestUtil; +import htsjdk.variant.variantcontext.Allele; +import htsjdk.variant.variantcontext.VariantContext; +import htsjdk.variant.variantcontext.VariantContextBuilder; +import htsjdk.variant.variantcontext.writer.VariantContextWriter; +import htsjdk.variant.variantcontext.writer.VariantContextWriterBuilder; +import htsjdk.variant.vcf.VCFHeader; +import htsjdk.variant.vcf.VCFHeaderLineType; +import htsjdk.variant.vcf.VCFInfoHeaderLine; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.zip.GZIPInputStream; + +/** + * Tests for the integration between {@link SeekableStream} and {@link GZIPInputStream}. + * + *

{@link GZIPInputStream} has a confirmed bug, that it relies on the {@link InputStream#available()} + * method to detect end-of-file, which is unsafe given its contract (see the Oracle's bug tracker + * issue https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7036144#). + * + *

Previous implementations of {@link SeekableStream} didn't implement {@link InputStream#available()}, + * returning always 0 (see https://github.com/samtools/htsjdk/issues/898). This test confirm that if + * the method is not implemented, a premature end-of-file can be detected prematurely. + * + * @author Daniel Gomez-Sanchez (magicDGS) + */ +public class SeekableStreamGZIPinputStreamIntegrationTest extends HtsjdkTest { + private static final String TEST_CHR = "1"; + private static Collection alleles = Arrays.asList(Allele.create("A", true), Allele.create("C")); + private static String RANDOM_ATTRIBUTE = "RD"; + + + private static File createBgzipVcfsWithVariableSize(final int firstRecordAttributeLength, final int nSmallRecords) throws Exception { + final VariantContext longRecord = new VariantContextBuilder("long", TEST_CHR, 1, 1, alleles) + .attribute(RANDOM_ATTRIBUTE, generateRandomString(firstRecordAttributeLength)) + .make(); + final File tempFile = Files.createTempFile("test" + firstRecordAttributeLength + "_" + nSmallRecords, ".vcf.gz").toFile(); + try (final VariantContextWriter writer = new VariantContextWriterBuilder() + .setOptions(VariantContextWriterBuilder.NO_OPTIONS) + .setOutputFile(tempFile) + .setOutputFileType(VariantContextWriterBuilder.OutputType.BLOCK_COMPRESSED_VCF) + .build()) { + writer.setHeader(createTestHeader()); // do not write the header + writer.add(longRecord); + for (int i = 2; i <= nSmallRecords + 1; i++) { + final VariantContext smallRecord = new VariantContextBuilder("short", TEST_CHR, i, i, alleles).attribute(RANDOM_ATTRIBUTE, ".").make(); + writer.add(smallRecord); + } + } + return tempFile; + } + + + private static VCFHeader createTestHeader() { + final VCFHeader header = new VCFHeader(); + header.addMetaDataLine(new VCFInfoHeaderLine(RANDOM_ATTRIBUTE, 1, VCFHeaderLineType.Character, "random string")); + return header; + } + + private static String generateRandomString(final int length) { + final Random random = new Random(TestUtil.RANDOM_SEED); + final StringBuilder builder = new StringBuilder(length); + for (int i = 0; i < length; i++) { + // generate number from 0 to 9, and append to the builder + builder.append(random.nextInt(10)); + } + return builder.toString(); + } + + @DataProvider + public Iterator compressedVcfsToTest() throws Exception { + final List data = new ArrayList<>(); + final int nSmallRecords = 1000000; + for (int firstRecordLength = 1000; firstRecordLength <= 10000; firstRecordLength+=1000) { + data.add(new Object[]{createBgzipVcfsWithVariableSize(firstRecordLength, nSmallRecords), nSmallRecords+1}); + } + return data.iterator(); + } + + @Test(dataProvider = "compressedVcfsToTest") + public void testWrappedSeekableStreamInGZIPinputStream(final File input, final long nLines) throws Exception { + try (final LineReader reader = new BufferedLineReader(new GZIPInputStream(new SeekableFileStream(input)))) { + for (int i = 0; i < nLines; i++) { + Assert.assertNotNull(reader.readLine(), "line #" + reader.getLineNumber()); + } + Assert.assertNull(reader.readLine()); + Assert.assertEquals(reader.getLineNumber(), nLines); + } + } + + @Test(dataProvider = "compressedVcfsToTest") + public void testConsistencyWithBgzip(final File input, final long nLines) throws Exception { + try (final InputStream gzIs = new GZIPInputStream(new SeekableFileStream(input)); + final InputStream bgzIs = new BlockCompressedInputStream(input)) { + int bgz = bgzIs.read(); + while (bgz != -1) { + Assert.assertEquals(gzIs.read(), bgz); + bgz = bgzIs.read(); + } + Assert.assertEquals(gzIs.read(), bgz); + } + + } +} diff --git a/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamTest.java b/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamTest.java index 1a7a5b9858..d19f6b074f 100644 --- a/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamTest.java +++ b/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamTest.java @@ -25,7 +25,7 @@ package htsjdk.samtools.seekablestream; import htsjdk.HtsjdkTest; -import org.junit.Assert; +import org.testng.Assert; import org.testng.annotations.Test; import java.util.Random; @@ -65,6 +65,22 @@ public void testResetUnmark() throws Exception { Assert.assertEquals(stream.read(), current); } + @Test + public void testAvailable() throws Exception { + // initiate random stream + final int length = 100; + final SeekableStream stream = getRandomSeekableStream(length); + // check that available returns the length + Assert.assertEquals(stream.available(), length); + // consume the stream + for(int i = 1; i < length + 1; i++) { + Assert.assertNotEquals(stream.read(), -1); + Assert.assertEquals(stream.available(), length - i); + } + // once consumed, no stream available + Assert.assertEquals(stream.available(), 0); + } + private static SeekableStream getRandomSeekableStream(final int size) { // generate random array final byte[] array = new byte[size]; diff --git a/src/test/java/htsjdk/samtools/util/BinaryCodecTest.java b/src/test/java/htsjdk/samtools/util/BinaryCodecTest.java index a47bb22e43..1774289d06 100644 --- a/src/test/java/htsjdk/samtools/util/BinaryCodecTest.java +++ b/src/test/java/htsjdk/samtools/util/BinaryCodecTest.java @@ -27,12 +27,7 @@ import org.testng.Assert; import org.testng.annotations.Test; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; /* @@ -284,5 +279,11 @@ public void timeTest() throws IOException{ readCodec.close(); } - + @Test + public void testReadBytesOrFewerNoneAvailable() { + final byte[] value = new byte[0]; + final ByteArrayInputStream instream = new ByteArrayInputStream(value); + final BinaryCodec readCodec = new BinaryCodec(instream); + Assert.assertEquals(readCodec.readBytesOrFewer(value, 0, 0), 0); + } } diff --git a/src/test/java/htsjdk/samtools/util/IOUtilTest.java b/src/test/java/htsjdk/samtools/util/IOUtilTest.java new file mode 100644 index 0000000000..638068f021 --- /dev/null +++ b/src/test/java/htsjdk/samtools/util/IOUtilTest.java @@ -0,0 +1,724 @@ +/* + * 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.util; + +import htsjdk.HtsjdkTest; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; + +import java.io.*; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.spi.FileSystemProvider; + +import htsjdk.samtools.BamFileIoUtils; +import htsjdk.samtools.SAMException; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.IllegalArgumentException; +import java.nio.file.Path; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.Random; +import java.util.stream.Stream; + + +public class IOUtilTest extends HtsjdkTest { + + + private static final Path TEST_DATA_DIR = Paths.get ("src/test/resources/htsjdk/samtools/io/"); + private static final Path TEST_VARIANT_DIR = Paths.get("src/test/resources/htsjdk/variant/"); + private static final Path SLURP_TEST_FILE = TEST_DATA_DIR.resolve("slurptest.txt"); + private static final Path EMPTY_FILE = TEST_DATA_DIR.resolve("empty.txt"); + private static final Path FIVE_SPACES_THEN_A_NEWLINE_THEN_FIVE_SPACES_FILE = TEST_DATA_DIR.resolve("5newline5.txt"); + private static final List SLURP_TEST_LINES = Arrays.asList("bacon and rice ", "for breakfast ", "wont you join me"); + private static final String SLURP_TEST_LINE_SEPARATOR = "\n"; + private static final String TEST_FILE_PREFIX = "htsjdk-IOUtilTest"; + private static final String TEST_FILE_EXTENSIONS[] = {".txt", ".txt.gz"}; + private static final String TEST_STRING = "bar!"; + + private File existingTempFile; + private String systemUser; + private String systemTempDir; + private FileSystem inMemoryFileSystem; + private static Path WORDS_LONG; + + @BeforeClass + public void setUp() throws IOException { + existingTempFile = File.createTempFile("FiletypeTest.", ".tmp"); + existingTempFile.deleteOnExit(); + systemTempDir = System.getProperty("java.io.tmpdir"); + final File tmpDir = new File(systemTempDir); + inMemoryFileSystem = Jimfs.newFileSystem(Configuration.unix());; + if (!tmpDir.isDirectory()) tmpDir.mkdir(); + if (!tmpDir.isDirectory()) + throw new RuntimeException("java.io.tmpdir (" + systemTempDir + ") is not a directory"); + systemUser = System.getProperty("user.name"); + //build long file of random words for compression testing + WORDS_LONG = Files.createTempFile("words_long", ".txt"); + WORDS_LONG.toFile().deleteOnExit(); + final List wordsList = Files.lines(TEST_DATA_DIR.resolve("dictionary_english_short.dic")).collect(Collectors.toList()); + final int numberOfWords = 300000; + final int seed = 345987345; + final Random rand = new Random(seed); + try (final BufferedWriter writer = Files.newBufferedWriter(WORDS_LONG)) { + for (int i = 0; i < numberOfWords; i++) { + writer.write(wordsList.get(rand.nextInt(wordsList.size()))); + } + } + } + + @AfterClass + public void tearDown() throws IOException { + // reset java properties to original + System.setProperty("java.io.tmpdir", systemTempDir); + System.setProperty("user.name", systemUser); + inMemoryFileSystem.close(); + } + + @Test + public void testFileReadingAndWriting() throws IOException { + String randomizedTestString = TEST_STRING + System.currentTimeMillis(); + for (String ext : TEST_FILE_EXTENSIONS) { + File f = File.createTempFile(TEST_FILE_PREFIX, ext); + f.deleteOnExit(); + + OutputStream os = IOUtil.openFileForWriting(f); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os)); + writer.write(randomizedTestString); + writer.close(); + + InputStream is = IOUtil.openFileForReading(f); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line = reader.readLine(); + Assert.assertEquals(randomizedTestString, line); + } + } + + @Test(groups = {"unix"}) + public void testGetCanonicalPath() throws IOException { + String tmpPath = System.getProperty("java.io.tmpdir"); + String userName = System.getProperty("user.name"); + + if (tmpPath.endsWith(userName)) { + tmpPath = tmpPath.substring(0, tmpPath.length() - userName.length()); + } + + File tmpDir = new File(tmpPath, userName); + tmpDir.mkdir(); + tmpDir.deleteOnExit(); + File actual = new File(tmpDir, "actual.txt"); + actual.deleteOnExit(); + ProcessExecutor.execute(new String[]{"touch", actual.getAbsolutePath()}); + File symlink = new File(tmpDir, "symlink.txt"); + symlink.deleteOnExit(); + ProcessExecutor.execute(new String[]{"ln", "-s", actual.getAbsolutePath(), symlink.getAbsolutePath()}); + File lnDir = new File(tmpDir, "symLinkDir"); + lnDir.deleteOnExit(); + ProcessExecutor.execute(new String[]{"ln", "-s", tmpDir.getAbsolutePath(), lnDir.getAbsolutePath()}); + File lnToActual = new File(lnDir, "actual.txt"); + lnToActual.deleteOnExit(); + File lnToSymlink = new File(lnDir, "symlink.txt"); + lnToSymlink.deleteOnExit(); + + File files[] = {actual, symlink, lnToActual, lnToSymlink}; + for (File f : files) { + Assert.assertEquals(IOUtil.getFullCanonicalPath(f), actual.getCanonicalPath()); + } + } + + @Test + public void testUtfWriting() throws IOException { + final String utf8 = new StringWriter().append((char) 168).append((char) 197).toString(); + for (String ext : TEST_FILE_EXTENSIONS) { + final File f = File.createTempFile(TEST_FILE_PREFIX, ext); + f.deleteOnExit(); + + final BufferedWriter writer = IOUtil.openFileForBufferedUtf8Writing(f); + writer.write(utf8); + CloserUtil.close(writer); + + final BufferedReader reader = IOUtil.openFileForBufferedUtf8Reading(f); + final String line = reader.readLine(); + Assert.assertEquals(utf8, line, f.getAbsolutePath()); + + CloserUtil.close(reader); + + } + } + + @Test + public void slurpLinesTest() throws FileNotFoundException { + Assert.assertEquals(IOUtil.slurpLines(SLURP_TEST_FILE.toFile()), SLURP_TEST_LINES); + } + + @Test + public void slurpWhitespaceOnlyFileTest() throws FileNotFoundException { + Assert.assertEquals(IOUtil.slurp(FIVE_SPACES_THEN_A_NEWLINE_THEN_FIVE_SPACES_FILE.toFile()), " \n "); + } + + @Test + public void slurpEmptyFileTest() throws FileNotFoundException { + Assert.assertEquals(IOUtil.slurp(EMPTY_FILE.toFile()), ""); + } + + @Test + public void slurpTest() throws FileNotFoundException { + Assert.assertEquals(IOUtil.slurp(SLURP_TEST_FILE.toFile()), CollectionUtil.join(SLURP_TEST_LINES, SLURP_TEST_LINE_SEPARATOR)); + } + + @Test(dataProvider = "fileTypeTestCases") + public void testFileType(final String path, boolean expectedIsRegularFile) { + final File file = new File(path); + Assert.assertEquals(IOUtil.isRegularPath(file), expectedIsRegularFile); + Assert.assertEquals(IOUtil.isRegularPath(file.toPath()), expectedIsRegularFile); + } + + @Test(dataProvider = "unixFileTypeTestCases", groups = {"unix"}) + public void testFileTypeUnix(final String path, boolean expectedIsRegularFile) { + final File file = new File(path); + Assert.assertEquals(IOUtil.isRegularPath(file), expectedIsRegularFile); + Assert.assertEquals(IOUtil.isRegularPath(file.toPath()), expectedIsRegularFile); + } + + @Test + public void testAddExtension() throws IOException { + Path p = IOUtil.getPath("/folder/file"); + Assert.assertEquals(IOUtil.addExtension(p, ".ext"), IOUtil.getPath("/folder/file.ext")); + p = IOUtil.getPath("folder/file"); + Assert.assertEquals(IOUtil.addExtension(p, ".ext"), IOUtil.getPath("folder/file.ext")); + try (FileSystem jimfs = Jimfs.newFileSystem(Configuration.unix())) { + p = jimfs.getPath("folder/sub/file"); + Assert.assertEquals(IOUtil.addExtension(p, ".ext"), jimfs.getPath("folder/sub/file.ext")); + p = jimfs.getPath("folder/file"); + Assert.assertEquals(IOUtil.addExtension(p, ".ext"), jimfs.getPath("folder/file.ext")); + p = jimfs.getPath("file"); + Assert.assertEquals(IOUtil.addExtension(p, ".ext"), jimfs.getPath("file.ext")); + } + } + + @Test + public void testAddExtensionOnList() throws IOException { + Path p = IOUtil.getPath("/folder/file"); + List fileSystemProviders = FileSystemProvider.installedProviders(); + + List paths = new ArrayList<>(); + List strings = new ArrayList<>(); + + paths.add(IOUtil.addExtension(p, ".ext")); + strings.add("/folder/file.ext"); + + p = IOUtil.getPath("folder/file"); + paths.add(IOUtil.addExtension(p, ".ext")); + strings.add("folder/file.ext"); + + List expectedPaths = IOUtil.getPaths(strings); + + Assert.assertEquals(paths, expectedPaths); + } + + + @DataProvider(name = "fileTypeTestCases") + private Object[][] fileTypeTestCases() { + return new Object[][]{ + {existingTempFile.getAbsolutePath(), Boolean.TRUE}, + {systemTempDir, Boolean.FALSE} + + }; + } + + @DataProvider(name = "unixFileTypeTestCases") + private Object[][] unixFileTypeTestCases() { + return new Object[][]{ + {"/dev/null", Boolean.FALSE}, + {"/dev/stdout", Boolean.FALSE}, + {"/non/existent/file", Boolean.TRUE}, + }; + } + + + @DataProvider + public Object[][] getFiles(){ + final File file = new File("someFile"); + return new Object[][] { + {null, null}, + {file, file.toPath()} + }; + } + + @Test(dataProvider = "getFiles") + public void testToPath(final File file, final Path expected){ + Assert.assertEquals(IOUtil.toPath(file), expected); + } + + + @DataProvider(name = "fileNamesForDelete") + public Object[][] fileNamesForDelete() { + return new Object[][] { + {Collections.emptyList()}, + {Collections.singletonList("file1")}, + {Arrays.asList("file1", "file2")} + }; + } + + @Test + public void testGetDefaultTmpDirPath() throws Exception { + try { + Path testPath = IOUtil.getDefaultTmpDirPath(); + Assert.assertEquals(testPath.toFile().getAbsolutePath(), new File(systemTempDir).getAbsolutePath() + "/" + systemUser); + + // change the properties to test others + final String newTempPath = Files.createTempDirectory("testGetDefaultTmpDirPath").toString(); + final String newUser = "my_user"; + System.setProperty("java.io.tmpdir", newTempPath); + System.setProperty("user.name", newUser); + testPath = IOUtil.getDefaultTmpDirPath(); + Assert.assertEquals(testPath.toFile().getAbsolutePath(), new File(newTempPath).getAbsolutePath() + "/" + newUser); + + } finally { + // reset system properties + System.setProperty("java.io.tmpdir", systemTempDir); + System.setProperty("user.name", systemUser); + } + } + + @Test(dataProvider = "fileNamesForDelete") + public void testDeletePathLocal(final List fileNames) throws Exception { + final File tmpDir = IOUtil.createTempDir("testDeletePath", ""); + final List paths = createLocalFiles(tmpDir, fileNames); + testDeletePath(paths); + } + + @Test(dataProvider = "fileNamesForDelete") + public void testDeletePathJims(final List fileNames) throws Exception { + final List paths = createJimfsFiles("testDeletePath", fileNames); + testDeletePath(paths); + } + + @Test(dataProvider = "fileNamesForDelete") + public void testDeleteArrayPathLocal(final List fileNames) throws Exception { + final File tmpDir = IOUtil.createTempDir("testDeletePath", ""); + final List paths = createLocalFiles(tmpDir, fileNames); + testDeletePathArray(paths); + } + + @Test(dataProvider = "fileNamesForDelete") + public void testDeleteArrayPathJims(final List fileNames) throws Exception { + final List paths = createJimfsFiles("testDeletePath", fileNames); + testDeletePathArray(paths); + } + + private static void testDeletePath(final List paths) { + paths.forEach(p -> Assert.assertTrue(Files.exists(p))); + IOUtil.deletePaths(paths); + paths.forEach(p -> Assert.assertFalse(Files.exists(p))); + } + + private static void testDeletePathArray(final List paths) { + paths.forEach(p -> Assert.assertTrue(Files.exists(p))); + IOUtil.deletePaths(paths.toArray(new Path[paths.size()])); + paths.forEach(p -> Assert.assertFalse(Files.exists(p))); + } + + private static List createLocalFiles(final File tmpDir, final List fileNames) throws Exception { + final List paths = new ArrayList<>(fileNames.size()); + for (final String f: fileNames) { + final File file = new File(tmpDir, f); + Assert.assertTrue(file.createNewFile(), "failed to create test file" +file); + paths.add(file.toPath()); + } + return paths; + } + + private List createJimfsFiles(final String folderName, final List fileNames) throws Exception { + final List paths = new ArrayList<>(fileNames.size()); + final Path folder = inMemoryFileSystem.getPath(folderName); + if (Files.notExists(folder)) Files.createDirectory(folder); + + for (final String f: fileNames) { + final Path p = inMemoryFileSystem.getPath(folderName, f); + Files.createFile(p); + paths.add(p); + } + + return paths; + } + + @DataProvider + public Object[][] pathsForWritableDirectory() throws Exception { + return new Object[][] { + // non existent + {inMemoryFileSystem.getPath("no_exists"), false}, + // non directory + {Files.createFile(inMemoryFileSystem.getPath("testAssertDirectoryIsWritable_file")), false}, + // TODO - how to do in inMemoryFileSystem a non-writable directory? + // writable directory + {Files.createDirectory(inMemoryFileSystem.getPath("testAssertDirectoryIsWritable_directory")), true} + }; + } + + @Test(dataProvider = "pathsForWritableDirectory") + public void testAssertDirectoryIsWritablePath(final Path path, final boolean writable) { + try { + IOUtil.assertDirectoryIsWritable(path); + } catch (SAMException e) { + if (writable) { + Assert.fail(e.getMessage()); + } + } + } + + @DataProvider + public Object[][] filesForWritableDirectory() throws Exception { + final File nonWritableFile = new File(systemTempDir, "testAssertDirectoryIsWritable_non_writable_dir"); + nonWritableFile.mkdir(); + nonWritableFile.setWritable(false); + + return new Object[][] { + // non existent + {new File("no_exists"), false}, + // non directory + {existingTempFile, false}, + // non-writable directory + {nonWritableFile, false}, + // writable directory + {new File(systemTempDir), true}, + }; + } + + @Test(dataProvider = "filesForWritableDirectory") + public void testAssertDirectoryIsWritableFile(final File file, final boolean writable) { + try { + IOUtil.assertDirectoryIsWritable(file); + } catch (SAMException e) { + if (writable) { + Assert.fail(e.getMessage()); + } + } + } + + static final String level1 = "Level1.fofn"; + static final String level2 = "Level2.fofn"; + + @DataProvider + public Object[][] fofnData() throws IOException { + + Path fofnPath1 = inMemoryFileSystem.getPath(level1); + Files.copy(TEST_DATA_DIR.resolve(level1), fofnPath1); + + Path fofnPath2 = inMemoryFileSystem.getPath(level2); + Files.copy(TEST_DATA_DIR.resolve(level2), fofnPath2); + + return new Object[][]{ + {TEST_DATA_DIR + "/" + level1, new String[]{".vcf", ".vcf.gz"}, 2}, + {TEST_DATA_DIR + "/" + level2, new String[]{".vcf", ".vcf.gz"}, 4}, + {fofnPath1.toUri().toString(), new String[]{".vcf", ".vcf.gz"}, 2}, + {fofnPath2.toUri().toString(), new String[]{".vcf", ".vcf.gz"}, 4} + }; + } + + @Test(dataProvider = "fofnData") + public void testUnrollPaths(final String pathUri, final String[] extensions, final int expectedNumberOfUnrolledPaths) throws IOException { + Path p = IOUtil.getPath(pathUri); + List paths = IOUtil.unrollPaths(Collections.singleton(p), extensions); + + Assert.assertEquals(paths.size(), expectedNumberOfUnrolledPaths); + } + + @DataProvider(name = "blockCompressedExtensionExtensionStrings") + public static Object[][] createBlockCompressedExtensionStrings() { + return new Object[][] { + { "testzip.gz", true }, + { "test.gzip", true }, + { "test.bgz", true }, + { "test.bgzf", true }, + { "test.bzip2", false } + }; + } + + @Test(dataProvider = "blockCompressedExtensionExtensionStrings") + public void testBlockCompressionExtensionString(final String testString, final boolean expected) { + Assert.assertEquals(IOUtil.hasBlockCompressedExtension(testString), expected); + } + + @Test(dataProvider = "blockCompressedExtensionExtensionStrings") + public void testBlockCompressionExtensionFile(final String testString, final boolean expected) { + Assert.assertEquals(IOUtil.hasBlockCompressedExtension(new File(testString)), expected); + } + + @DataProvider(name = "blockCompressedExtensionExtensionURIStrings") + public static Object[][] createBlockCompressedExtensionURIs() { + return new Object[][]{ + {"testzip.gz", true}, + {"test.gzip", true}, + {"test.bgz", true}, + {"test.bgzf", true}, + {"test", false}, + {"test.bzip2", false}, + + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.gz", true}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.gzip", true}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bgz", true}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bgzf", true}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bzip2", false}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877", false}, + + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.gz?alt=media", true}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.gzip?alt=media", true}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bgz?alt=media", true}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bgzf?alt=media", true}, + {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bzip2?alt=media", false}, + + {"ftp://ftp.broadinstitute.org/distribution/igv/TEST/cpgIslands.hg18.gz", true}, + {"ftp://ftp.broadinstitute.org/distribution/igv/TEST/cpgIslands.hg18.bed", false} + }; + } + + @Test(dataProvider = "blockCompressedExtensionExtensionURIStrings") + public void testBlockCompressionExtension(final String testURIString, final boolean expected) { + URI testURI = URI.create(testURIString); + Assert.assertEquals(IOUtil.hasBlockCompressedExtension(testURI), expected); + } + + @Test(dataProvider = "blockCompressedExtensionExtensionURIStrings") + public void testBlockCompressionExtensionStringVersion(final String testURIString, final boolean expected) { + Assert.assertEquals(IOUtil.hasBlockCompressedExtension(testURIString), expected); + } + + @DataProvider + public static Object[][] blockCompressedFiles() { + return new Object[][]{ + {TEST_DATA_DIR.resolve("ipsum.txt"), true, false}, + {TEST_DATA_DIR.resolve("ipsum.txt"), false, false}, + {TEST_DATA_DIR.resolve("ipsum.txt.gz"), true, false}, + {TEST_DATA_DIR.resolve("ipsum.txt.gz"), false, false}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgz"), true, true}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgz"), false, true}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgz.wrongextension"), true, false}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgz.wrongextension"), false, true}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgzipped_with_gzextension.gz"), true, true}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgzipped_with_gzextension.gz"), false, true}, + {TEST_DATA_DIR.resolve("example.bam"), true, false}, + {TEST_DATA_DIR.resolve("example.bam"), false, true} + }; + } + + @Test(dataProvider = "blockCompressedFiles") + public void testIsBlockCompressed(Path file, boolean checkExtension, boolean expected) throws IOException { + Assert.assertEquals(IOUtil.isBlockCompressed(file, checkExtension), expected); + } + + @Test(dataProvider = "blockCompressedFiles") + public void testIsBlockCompressedOnJimfs(Path file, boolean checkExtension, boolean expected) throws IOException { + try (FileSystem jimfs = Jimfs.newFileSystem(Configuration.unix())) { + final Path jimfsRoot = jimfs.getRootDirectories().iterator().next(); + final Path jimfsFile = Files.copy(file, jimfsRoot.resolve(file.getFileName().toString())); + Assert.assertEquals(IOUtil.isBlockCompressed(jimfsFile, checkExtension), expected); + } + } + + @DataProvider + public static Object[][] filesToCompress() { + return new Object[][]{ + {WORDS_LONG, ".gz", 8}, + {WORDS_LONG, ".bfq", 8}, + {TEST_VARIANT_DIR.resolve("test1.vcf"), ".gz", 7}, + {TEST_VARIANT_DIR.resolve("test1.vcf"), ".bfq", 7} + }; + } + + @Test(dataProvider = "filesToCompress") + public void testCompressionLevel(final Path file, final String extension, final int lastDifference) throws IOException { + final long origSize = Files.size(file); + long previousSize = origSize; + for (int compressionLevel = 1; compressionLevel <= 9; compressionLevel++) { + final Path outFile = Files.createTempFile("tmp", extension); + outFile.toFile().deleteOnExit(); + IOUtil.setCompressionLevel(compressionLevel); + Assert.assertEquals(IOUtil.getCompressionLevel(), compressionLevel); + final InputStream inStream = IOUtil.openFileForReading(file); + try (final OutputStream outStream = IOUtil.openFileForWriting(outFile.toFile())) { + IOUtil.transferByStream(inStream, outStream, origSize); + } + final long newSize = Files.size(outFile); + if (compressionLevel <= lastDifference) { + Assert.assertTrue(previousSize > newSize); + } else { + Assert.assertTrue(previousSize >= newSize); + } + previousSize = newSize; + } + } + + @DataProvider + public static Object[][] badCompressionLevels() { + return new Object[][]{ + {-1}, + {10} + }; + } + + @Test(dataProvider = "badCompressionLevels", expectedExceptions = {IllegalArgumentException.class}) + public void testCompressionLevelExceptions(final int compressionLevel) { + IOUtil.setCompressionLevel(compressionLevel); + } + + @DataProvider + public static Object[][] filesToCopy() { + return new Object[][]{ + {TEST_VARIANT_DIR.resolve("test1.vcf")}, + {TEST_DATA_DIR.resolve("ipsum.txt")} + }; + } + + @Test(dataProvider = "filesToCopy") + public void testCopyFile(final Path file) throws IOException { + final Path outFile = Files.createTempFile("tmp", ".tmp"); + outFile.toFile().deleteOnExit(); + IOUtil.copyFile(file.toFile(), outFile.toFile()); + Assert.assertEquals(Files.lines(file).collect(Collectors.toList()), Files.lines(outFile).collect(Collectors.toList())); + } + + @Test(dataProvider = "filesToCopy", expectedExceptions = {SAMException.class}) + public void testCopyFileReadException(final Path file) throws IOException { + final Path outFile = Files.createTempFile("tmp", ".tmp"); + outFile.toFile().deleteOnExit(); + file.toFile().setReadable(false); + try { + IOUtil.copyFile(file.toFile(), outFile.toFile()); + } finally { //need to set input file permission back to readable so other unit tests can access it + file.toFile().setReadable(true); + } + } + + @Test(dataProvider = "filesToCopy", expectedExceptions = {SAMException.class}) + public void testCopyFileWriteException(final Path file) throws IOException { + final Path outFile = Files.createTempFile("tmp", ".tmp"); + outFile.toFile().deleteOnExit(); + outFile.toFile().setWritable(false); + IOUtil.copyFile(file.toFile(), outFile.toFile()); + } + + @DataProvider + public static Object[][] baseNameTests() { + return new Object[][]{ + {TEST_DATA_DIR.resolve("ipsum.txt"), "ipsum"}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgz.wrongextension"), "ipsum.txt.bgz"}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgzipped_with_gzextension.gz"), "ipsum.txt.bgzipped_with_gzextension"}, + {TEST_VARIANT_DIR.resolve("utils"), "utils"}, + {TEST_VARIANT_DIR.resolve("not_real_file.txt"), "not_real_file"} + }; + } + + @Test(dataProvider = "baseNameTests") + public void testBasename(final Path file, final String expected) { + final String result = IOUtil.basename(file.toFile()); + Assert.assertEquals(result, expected); + } + + @DataProvider + public static Object[][] regExpTests() { + return new Object[][]{ + {"\\w+\\.txt", new String[]{"5newline5.txt", "empty.txt", "ipsum.txt", "slurptest.txt"}}, + {"^((?!txt).)*$", new String[]{"Level1.fofn", "Level2.fofn", "example.bam"}}, + {"^\\d+.*", new String[]{"5newline5.txt"}} + }; + } + + @Test(dataProvider = "regExpTests") + public void testRegExp(final String regexp, final String[] expected) throws IOException { + final String[] allNames = {"5newline5.txt", "Level2.fofn", "example.bam", "ipsum.txt.bgz", "ipsum.txt.bgzipped_with_gzextension.gz", "slurptest.txt", "Level1.fofn", "empty.txt", "ipsum.txt", "ipsum.txt.bgz.wrongextension", "ipsum.txt.gz"}; + final Path regExpDir = Files.createTempDirectory("regExpDir"); + regExpDir.toFile().deleteOnExit(); + final List listExpected = Arrays.asList(expected); + final List expectedFiles = new ArrayList(); + for (String name : allNames) { + final Path file = regExpDir.resolve(name); + file.toFile().deleteOnExit(); + file.toFile().createNewFile(); + if (listExpected.contains(name)) { + expectedFiles.add(file.toFile()); + } + } + final File[] result = IOUtil.getFilesMatchingRegexp(regExpDir.toFile(), regexp); + Assert.assertEqualsNoOrder(result, expectedFiles.toArray()); + } + + @Test() + public void testReadLines() throws IOException { + final Path file = Files.createTempFile("tmp", ".txt"); + file.toFile().deleteOnExit(); + final int seed = 12394738; + final Random rand = new Random(seed); + final int nLines = 5; + final List lines = new ArrayList(); + try (final PrintWriter writer = new PrintWriter(Files.newBufferedWriter(file))) { + for (int i = 0; i < nLines; i++) { + final String line = TEST_STRING + Integer.toString(rand.nextInt(100000000)); + lines.add(line); + writer.println(line); + } + } + final List retLines = new ArrayList(); + IOUtil.readLines(file.toFile()).forEachRemaining(retLines::add); + Assert.assertEquals(retLines, lines); + } + + @DataProvider + public static Object[][] fileSuffixTests() { + return new Object[][]{ + {TEST_DATA_DIR.resolve("ipsum.txt"), ".txt"}, + {TEST_DATA_DIR.resolve("ipsum.txt.bgz"), ".bgz"}, + {TEST_DATA_DIR, null} + }; + } + + @Test(dataProvider = "fileSuffixTests") + public void testSuffixTest(final Path file, final String expected) { + final String ret = IOUtil.fileSuffix(file.toFile()); + Assert.assertEquals(ret, expected); + } + + @Test + public void testCopyDirectoryTree() throws IOException { + final Path copyToDir = Files.createTempDirectory("copyToDir"); + copyToDir.toFile().deleteOnExit(); + IOUtil.copyDirectoryTree(TEST_VARIANT_DIR.toFile(), copyToDir.toFile()); + final List collect = Files.walk(TEST_VARIANT_DIR).filter(f -> !f.equals(TEST_VARIANT_DIR)).map(p -> p.getFileName()).collect(Collectors.toList()); + final List collectCopy = Files.walk(copyToDir).filter(f -> !f.equals(copyToDir)).map(p -> p.getFileName()).collect(Collectors.toList()); + Assert.assertEqualsNoOrder(collect.toArray(), collectCopy.toArray()); + } +} + diff --git a/src/test/java/htsjdk/samtools/util/IntervalListTest.java b/src/test/java/htsjdk/samtools/util/IntervalListTest.java index 4dbd03902a..526ff75151 100644 --- a/src/test/java/htsjdk/samtools/util/IntervalListTest.java +++ b/src/test/java/htsjdk/samtools/util/IntervalListTest.java @@ -482,7 +482,7 @@ public void testFromVCF(final String vcf, final String compInterval, final boole final File compIntervalFile = new File(compInterval); final IntervalList compList = IntervalList.fromFile(compIntervalFile); - final IntervalList list = invertVCF ? IntervalList.invert(VCFFileReader.fromVcf(vcfFile)) : VCFFileReader.fromVcf(vcfFile); + final IntervalList list = invertVCF ? IntervalList.invert(VCFFileReader.toIntervalList(vcfFile.toPath())) : VCFFileReader.toIntervalList(vcfFile.toPath()); compList.getHeader().getSequenceDictionary().assertSameDictionary(list.getHeader().getSequenceDictionary()); @@ -513,7 +513,7 @@ public void testFromVCFWithPath(final String vcf, final String compInterval, fin final File compIntervalFile = new File(compInterval); final IntervalList compList = IntervalList.fromFile(compIntervalFile); - final IntervalList list = invertVCF ? IntervalList.invert(VCFFileReader.fromVcf(vcfFile)) : VCFFileReader.fromVcf(vcfFile); + final IntervalList list = invertVCF ? IntervalList.invert(VCFFileReader.toIntervalList(vcfFile.toPath())) : VCFFileReader.toIntervalList(vcfFile.toPath()); compList.getHeader().getSequenceDictionary().assertSameDictionary(list.getHeader().getSequenceDictionary()); @@ -661,6 +661,6 @@ public void changeHeader() { public void testContigsAbsentInHeader() { String vcf = "src/test/resources/htsjdk/samtools/intervallist/IntervalListFromVCFNoContigLines.vcf"; final File vcfFile = new File(vcf); - VCFFileReader.fromVcf(vcfFile); + VCFFileReader.toIntervalList(vcfFile.toPath()); } } diff --git a/src/test/java/htsjdk/samtools/util/IoUtilTest.java b/src/test/java/htsjdk/samtools/util/IoUtilTest.java deleted file mode 100644 index f4e31024f2..0000000000 --- a/src/test/java/htsjdk/samtools/util/IoUtilTest.java +++ /dev/null @@ -1,450 +0,0 @@ -/* - * 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.util; - -import htsjdk.HtsjdkTest; -import com.google.common.jimfs.Configuration; -import com.google.common.jimfs.Jimfs; -import java.nio.file.FileSystem; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.spi.FileSystemProvider; - -import htsjdk.samtools.SAMException; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class IoUtilTest extends HtsjdkTest { - - - private static final Path TEST_DATA_DIR = Paths.get ("src/test/resources/htsjdk/samtools/io/"); - private static final Path SLURP_TEST_FILE = TEST_DATA_DIR.resolve("slurptest.txt"); - private static final Path EMPTY_FILE = TEST_DATA_DIR.resolve("empty.txt"); - private static final Path FIVE_SPACES_THEN_A_NEWLINE_THEN_FIVE_SPACES_FILE = TEST_DATA_DIR.resolve("5newline5.txt"); - private static final List SLURP_TEST_LINES = Arrays.asList("bacon and rice ", "for breakfast ", "wont you join me"); - private static final String SLURP_TEST_LINE_SEPARATOR = "\n"; - private static final String TEST_FILE_PREFIX = "htsjdk-IOUtilTest"; - private static final String TEST_FILE_EXTENSIONS[] = {".txt", ".txt.gz"}; - private static final String TEST_STRING = "bar!"; - private File existingTempFile; - private String systemUser; - private String systemTempDir; - - private FileSystem inMemoryfileSystem; - - @BeforeClass - public void setUp() throws IOException { - existingTempFile = File.createTempFile("FiletypeTest.", ".tmp"); - existingTempFile.deleteOnExit(); - systemTempDir = System.getProperty("java.io.tmpdir"); - final File tmpDir = new File(systemTempDir); - inMemoryfileSystem = Jimfs.newFileSystem(Configuration.unix());; - if (!tmpDir.isDirectory()) tmpDir.mkdir(); - if (!tmpDir.isDirectory()) - throw new RuntimeException("java.io.tmpdir (" + systemTempDir + ") is not a directory"); - systemUser = System.getProperty("user.name"); - } - - @AfterClass - public void tearDown() throws IOException { - // reset java properties to original - System.setProperty("java.io.tmpdir", systemTempDir); - System.setProperty("user.name", systemUser); - inMemoryfileSystem.close(); - } - - @Test - public void testFileReadingAndWriting() throws IOException { - String randomizedTestString = TEST_STRING + System.currentTimeMillis(); - for (String ext : TEST_FILE_EXTENSIONS) { - File f = File.createTempFile(TEST_FILE_PREFIX, ext); - f.deleteOnExit(); - - OutputStream os = IOUtil.openFileForWriting(f); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os)); - writer.write(randomizedTestString); - writer.close(); - - InputStream is = IOUtil.openFileForReading(f); - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - String line = reader.readLine(); - Assert.assertEquals(randomizedTestString, line); - } - } - - @Test(groups = {"unix"}) - public void testGetCanonicalPath() throws IOException { - String tmpPath = System.getProperty("java.io.tmpdir"); - String userName = System.getProperty("user.name"); - - if (tmpPath.endsWith(userName)) { - tmpPath = tmpPath.substring(0, tmpPath.length() - userName.length()); - } - - File tmpDir = new File(tmpPath, userName); - tmpDir.mkdir(); - File actual = new File(tmpDir, "actual.txt"); - ProcessExecutor.execute(new String[]{"touch", actual.getAbsolutePath()}); - File symlink = new File(tmpDir, "symlink.txt"); - ProcessExecutor.execute(new String[]{"ln", "-s", actual.getAbsolutePath(), symlink.getAbsolutePath()}); - File lnDir = new File(tmpDir, "symLinkDir"); - ProcessExecutor.execute(new String[]{"ln", "-s", tmpDir.getAbsolutePath(), lnDir.getAbsolutePath()}); - File lnToActual = new File(lnDir, "actual.txt"); - File lnToSymlink = new File(lnDir, "symlink.txt"); - - - File files[] = {actual, symlink, lnToActual, lnToSymlink}; - for (File f : files) { - Assert.assertEquals(IOUtil.getFullCanonicalPath(f), actual.getCanonicalPath()); - } - - actual.delete(); - symlink.delete(); - lnToActual.delete(); - lnToSymlink.delete(); - lnDir.delete(); - tmpDir.delete(); - } - - @Test - public void testUtfWriting() throws IOException { - final String utf8 = new StringWriter().append((char) 168).append((char) 197).toString(); - for (String ext : TEST_FILE_EXTENSIONS) { - final File f = File.createTempFile(TEST_FILE_PREFIX, ext); - f.deleteOnExit(); - - final BufferedWriter writer = IOUtil.openFileForBufferedUtf8Writing(f); - writer.write(utf8); - CloserUtil.close(writer); - - final BufferedReader reader = IOUtil.openFileForBufferedUtf8Reading(f); - final String line = reader.readLine(); - Assert.assertEquals(utf8, line, f.getAbsolutePath()); - - CloserUtil.close(reader); - - } - } - - @Test - public void slurpLinesTest() throws FileNotFoundException { - Assert.assertEquals(IOUtil.slurpLines(SLURP_TEST_FILE.toFile()), SLURP_TEST_LINES); - } - - @Test - public void slurpWhitespaceOnlyFileTest() throws FileNotFoundException { - Assert.assertEquals(IOUtil.slurp(FIVE_SPACES_THEN_A_NEWLINE_THEN_FIVE_SPACES_FILE.toFile()), " \n "); - } - - @Test - public void slurpEmptyFileTest() throws FileNotFoundException { - Assert.assertEquals(IOUtil.slurp(EMPTY_FILE.toFile()), ""); - } - - @Test - public void slurpTest() throws FileNotFoundException { - Assert.assertEquals(IOUtil.slurp(SLURP_TEST_FILE.toFile()), CollectionUtil.join(SLURP_TEST_LINES, SLURP_TEST_LINE_SEPARATOR)); - } - - @Test(dataProvider = "fileTypeTestCases") - public void testFileType(final String path, boolean expectedIsRegularFile) { - final File file = new File(path); - Assert.assertEquals(IOUtil.isRegularPath(file), expectedIsRegularFile); - if (null != file) { - Assert.assertEquals(IOUtil.isRegularPath(file.toPath()), expectedIsRegularFile); - } - } - - @Test(dataProvider = "unixFileTypeTestCases", groups = {"unix"}) - public void testFileTypeUnix(final String path, boolean expectedIsRegularFile) { - final File file = new File(path); - Assert.assertEquals(IOUtil.isRegularPath(file), expectedIsRegularFile); - if (null != file) { - Assert.assertEquals(IOUtil.isRegularPath(file.toPath()), expectedIsRegularFile); - } - } - - @Test - public void testAddExtension() throws IOException { - Path p = IOUtil.getPath("/folder/file"); - List fileSystemProviders = FileSystemProvider.installedProviders(); - Assert.assertEquals(IOUtil.addExtension(p, ".ext"), IOUtil.getPath("/folder/file.ext")); - p = IOUtil.getPath("folder/file"); - Assert.assertEquals(IOUtil.addExtension(p, ".ext"), IOUtil.getPath("folder/file.ext")); - try (FileSystem jimfs = Jimfs.newFileSystem(Configuration.unix())) { - p = jimfs.getPath("folder/sub/file"); - Assert.assertEquals(IOUtil.addExtension(p, ".ext"), jimfs.getPath("folder/sub/file.ext")); - p = jimfs.getPath("folder/file"); - Assert.assertEquals(IOUtil.addExtension(p, ".ext"), jimfs.getPath("folder/file.ext")); - p = jimfs.getPath("file"); - Assert.assertEquals(IOUtil.addExtension(p, ".ext"), jimfs.getPath("file.ext")); - } - } - - @Test - public void testAddExtensionOnList() throws IOException { - Path p = IOUtil.getPath("/folder/file"); - List fileSystemProviders = FileSystemProvider.installedProviders(); - - List paths = new ArrayList<>(); - List strings = new ArrayList<>(); - - paths.add(IOUtil.addExtension(p, ".ext")); - strings.add("/folder/file.ext"); - - p = IOUtil.getPath("folder/file"); - paths.add(IOUtil.addExtension(p, ".ext")); - strings.add("folder/file.ext"); - - List expectedPaths = IOUtil.getPaths(strings); - - Assert.assertEquals(paths, expectedPaths); - } - - - @DataProvider(name = "fileTypeTestCases") - private Object[][] fileTypeTestCases() { - return new Object[][]{ - {existingTempFile.getAbsolutePath(), Boolean.TRUE}, - {systemTempDir, Boolean.FALSE} - - }; - } - - @DataProvider(name = "unixFileTypeTestCases") - private Object[][] unixFileTypeTestCases() { - return new Object[][]{ - {"/dev/null", Boolean.FALSE}, - {"/dev/stdout", Boolean.FALSE}, - {"/non/existent/file", Boolean.TRUE}, - }; - } - - @DataProvider(name = "fileNamesForDelete") - public Object[][] fileNamesForDelete() { - return new Object[][] { - {Collections.emptyList()}, - {Collections.singletonList("file1")}, - {Arrays.asList("file1", "file2")} - }; - } - - @Test - public void testGetDefaultTmpDirPath() throws Exception { - try { - Path testPath = IOUtil.getDefaultTmpDirPath(); - Assert.assertEquals(testPath.toFile().getAbsolutePath(), new File(systemTempDir).getAbsolutePath() + "/" + systemUser); - - // change the properties to test others - final String newTempPath = Files.createTempDirectory("testGetDefaultTmpDirPath").toString(); - final String newUser = "my_user"; - System.setProperty("java.io.tmpdir", newTempPath); - System.setProperty("user.name", newUser); - testPath = IOUtil.getDefaultTmpDirPath(); - Assert.assertEquals(testPath.toFile().getAbsolutePath(), new File(newTempPath).getAbsolutePath() + "/" + newUser); - - } finally { - // reset system properties - System.setProperty("java.io.tmpdir", systemTempDir); - System.setProperty("user.name", systemUser); - } - } - - @Test(dataProvider = "fileNamesForDelete") - public void testDeletePathLocal(final List fileNames) throws Exception { - final File tmpDir = IOUtil.createTempDir("testDeletePath", ""); - final List paths = createLocalFiles(tmpDir, fileNames); - testDeletePath(paths); - } - - @Test(dataProvider = "fileNamesForDelete") - public void testDeletePathJims(final List fileNames) throws Exception { - final List paths = createJimsFiles("testDeletePath", fileNames); - testDeletePath(paths); - } - - @Test(dataProvider = "fileNamesForDelete") - public void testDeleteArrayPathLocal(final List fileNames) throws Exception { - final File tmpDir = IOUtil.createTempDir("testDeletePath", ""); - final List paths = createLocalFiles(tmpDir, fileNames); - testDeletePathArray(paths); - } - - @Test(dataProvider = "fileNamesForDelete") - public void testDeleteArrayPathJims(final List fileNames) throws Exception { - final List paths = createJimsFiles("testDeletePath", fileNames); - testDeletePathArray(paths); - } - - private static void testDeletePath(final List paths) { - paths.forEach(p -> Assert.assertTrue(Files.exists(p))); - IOUtil.deletePaths(paths); - paths.forEach(p -> Assert.assertFalse(Files.exists(p))); - } - - private static void testDeletePathArray(final List paths) { - paths.forEach(p -> Assert.assertTrue(Files.exists(p))); - IOUtil.deletePaths(paths.toArray(new Path[paths.size()])); - paths.forEach(p -> Assert.assertFalse(Files.exists(p))); - } - - private static List createLocalFiles(final File tmpDir, final List fileNames) throws Exception { - final List paths = new ArrayList<>(fileNames.size()); - for (final String f: fileNames) { - final File file = new File(tmpDir, f); - file.createNewFile(); - paths.add(file.toPath()); - } - return paths; - } - - private List createJimsFiles(final String folderName, final List fileNames) throws Exception { - final List paths = new ArrayList<>(fileNames.size()); - final Path folder = inMemoryfileSystem.getPath(folderName); - if (Files.notExists(folder)) Files.createDirectory(folder); - - for (final String f: fileNames) { - final Path p = inMemoryfileSystem.getPath(folderName, f); - Files.createFile(p); - paths.add(p); - } - - return paths; - } - - @DataProvider - public Object[][] pathsForDeletePathThread() throws Exception { - return new Object[][] { - {File.createTempFile("testDeletePathThread", "file").toPath()}, - {Files.createFile(inMemoryfileSystem.getPath("testDeletePathThread"))} - }; - } - - @Test(dataProvider = "pathsForDeletePathThread") - public void testDeletePathThread(final Path path) throws Exception { - Assert.assertTrue(Files.exists(path)); - new IOUtil.DeletePathThread(path).run(); - Assert.assertFalse(Files.exists(path)); - } - - @DataProvider - public Object[][] pathsForWritableDirectory() throws Exception { - return new Object[][] { - // non existent - {inMemoryfileSystem.getPath("no_exists"), false}, - // non directory - {Files.createFile(inMemoryfileSystem.getPath("testAssertDirectoryIsWritable_file")), false}, - // TODO - how to do in inMemmoryFileSystem a non-writable directory? - // writable directory - {Files.createDirectory(inMemoryfileSystem.getPath("testAssertDirectoryIsWritable_directory")), true} - }; - } - - @Test(dataProvider = "pathsForWritableDirectory") - public void testAssertDirectoryIsWritablePath(final Path path, final boolean writable) { - try { - IOUtil.assertDirectoryIsWritable(path); - } catch (SAMException e) { - if (writable) { - Assert.fail(e.getMessage()); - } - } - } - - @DataProvider - public Object[][] filesForWritableDirectory() throws Exception { - final File nonWritableFile = new File(systemTempDir, "testAssertDirectoryIsWritable_non_writable_dir"); - nonWritableFile.mkdir(); - nonWritableFile.setWritable(false); - - return new Object[][] { - // non existent - {new File("no_exists"), false}, - // non directory - {existingTempFile, false}, - // non-writable directory - {nonWritableFile, false}, - // writable directory - {new File(systemTempDir), true}, - }; - } - - @Test(dataProvider = "filesForWritableDirectory") - public void testAssertDirectoryIsWritableFile(final File file, final boolean writable) { - try { - IOUtil.assertDirectoryIsWritable(file); - } catch (SAMException e) { - if (writable) { - Assert.fail(e.getMessage()); - } - } - } - - static final String level1 = "Level1.fofn"; - static final String level2 = "Level2.fofn"; - - @DataProvider - public Object[][] fofnData() throws IOException { - - Path fofnPath1 = inMemoryfileSystem.getPath(level1); - Files.copy(TEST_DATA_DIR.resolve(level1), fofnPath1); - - Path fofnPath2 = inMemoryfileSystem.getPath(level2); - Files.copy(TEST_DATA_DIR.resolve(level2), fofnPath2); - - return new Object[][]{ - {TEST_DATA_DIR + "/" + level1, new String[]{".vcf", ".vcf.gz"}, 2}, - {TEST_DATA_DIR + "/" + level2, new String[]{".vcf", ".vcf.gz"}, 4}, - {fofnPath1.toUri().toString(), new String[]{".vcf", ".vcf.gz"}, 2}, - {fofnPath2.toUri().toString(), new String[]{".vcf", ".vcf.gz"}, 4} - }; - } - - @Test(dataProvider = "fofnData") - public void testUnrollPaths(final String pathUri, final String[] extensions, final int expectedNumberOfUnrolledPaths) throws IOException { - Path p = IOUtil.getPath(pathUri); - List paths = IOUtil.unrollPaths(Collections.singleton(p), extensions); - - Assert.assertEquals(paths.size(), expectedNumberOfUnrolledPaths); - } -} diff --git a/src/test/java/htsjdk/tribble/AbstractFeatureReaderTest.java b/src/test/java/htsjdk/tribble/AbstractFeatureReaderTest.java index 3a5b77269d..e4d3d2bfd8 100644 --- a/src/test/java/htsjdk/tribble/AbstractFeatureReaderTest.java +++ b/src/test/java/htsjdk/tribble/AbstractFeatureReaderTest.java @@ -4,6 +4,8 @@ import com.google.common.jimfs.Jimfs; import htsjdk.HtsjdkTest; import htsjdk.samtools.FileTruncatedException; +import htsjdk.samtools.util.IOUtil; +import htsjdk.samtools.util.IOUtilTest; import htsjdk.samtools.util.TestUtil; import htsjdk.tribble.bed.BEDCodec; import htsjdk.tribble.bed.BEDFeature; @@ -67,7 +69,7 @@ public void testVcfOverHTTP() throws IOException { assertFalse(localIterator.hasNext()); } - @Test + @Test(groups = "ftp") public void testLoadBEDFTP() throws Exception { final String path = "ftp://ftp.broadinstitute.org/distribution/igv/TEST/cpgIslands with spaces.hg18.bed"; final BEDCodec codec = new BEDCodec(); @@ -77,62 +79,23 @@ public void testLoadBEDFTP() throws Exception { } } - @DataProvider(name = "blockCompressedExtensionExtensionStrings") - public Object[][] createBlockCompressedExtensionStrings() { - return new Object[][] { - { "testzip.gz", true }, - { "test.gzip", true }, - { "test.bgz", true }, - { "test.bgzf", true }, - { "test.bzip2", false } - }; - } - - @Test(dataProvider = "blockCompressedExtensionExtensionStrings") + @Test(dataProvider = "blockCompressedExtensionExtensionStrings", dataProviderClass = IOUtilTest.class) public void testBlockCompressionExtensionString(final String testString, final boolean expected) { Assert.assertEquals(AbstractFeatureReader.hasBlockCompressedExtension(testString), expected); } - @Test(dataProvider = "blockCompressedExtensionExtensionStrings") + @Test(dataProvider = "blockCompressedExtensionExtensionStrings", dataProviderClass = IOUtilTest.class) public void testBlockCompressionExtensionFile(final String testString, final boolean expected) { Assert.assertEquals(AbstractFeatureReader.hasBlockCompressedExtension(new File(testString)), expected); } - @DataProvider(name = "blockCompressedExtensionExtensionURIStrings") - public Object[][] createBlockCompressedExtensionURIs() { - return new Object[][]{ - {"testzip.gz", true}, - {"test.gzip", true}, - {"test.bgz", true}, - {"test.bgzf", true}, - {"test", false}, - {"test.bzip2", false}, - - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.gz", true}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.gzip", true}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bgz", true}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bgzf", true}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bzip2", false}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877", false}, - - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.gz?alt=media", true}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.gzip?alt=media", true}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bgz?alt=media", true}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bgzf?alt=media", true}, - {"https://www.googleapis.com/download/storage/v1/b/deflaux-public-test/o/NA12877.vcf.bzip2?alt=media", false}, - - {"ftp://ftp.broadinstitute.org/distribution/igv/TEST/cpgIslands.hg18.gz", true}, - {"ftp://ftp.broadinstitute.org/distribution/igv/TEST/cpgIslands.hg18.bed", false} - }; - } - - @Test(dataProvider = "blockCompressedExtensionExtensionURIStrings") + @Test(dataProvider = "blockCompressedExtensionExtensionURIStrings", dataProviderClass = IOUtilTest.class) public void testBlockCompressionExtension(final String testURIString, final boolean expected) { URI testURI = URI.create(testURIString); Assert.assertEquals(AbstractFeatureReader.hasBlockCompressedExtension(testURI), expected); } - @Test(dataProvider = "blockCompressedExtensionExtensionURIStrings") + @Test(dataProvider = "blockCompressedExtensionExtensionURIStrings", dataProviderClass = IOUtilTest.class) public void testBlockCompressionExtensionStringVersion(final String testURIString, final boolean expected) { Assert.assertEquals(AbstractFeatureReader.hasBlockCompressedExtension(testURIString), expected); } diff --git a/src/test/java/htsjdk/tribble/TestUtils.java b/src/test/java/htsjdk/tribble/TestUtils.java index b2ca9e7a50..c77f58a68e 100644 --- a/src/test/java/htsjdk/tribble/TestUtils.java +++ b/src/test/java/htsjdk/tribble/TestUtils.java @@ -18,12 +18,19 @@ package htsjdk.tribble; +import htsjdk.utils.TestNGUtils; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; /** * User: jacob diff --git a/src/test/java/htsjdk/tribble/bed/BEDCodecTest.java b/src/test/java/htsjdk/tribble/bed/BEDCodecTest.java index df8a95ed81..fe1f299732 100644 --- a/src/test/java/htsjdk/tribble/bed/BEDCodecTest.java +++ b/src/test/java/htsjdk/tribble/bed/BEDCodecTest.java @@ -27,6 +27,7 @@ import htsjdk.HtsjdkTest; import htsjdk.samtools.util.BlockCompressedFilePointerUtil; import htsjdk.samtools.util.BlockCompressedInputStream; +import htsjdk.samtools.util.IOUtil; import htsjdk.tribble.AbstractFeatureReader; import htsjdk.tribble.Feature; import htsjdk.tribble.FeatureReader; @@ -250,7 +251,7 @@ public void testGetTabixFormat() { public void testCanDecode() { final BEDCodec codec = new BEDCodec(); final String pattern = "filename.%s%s"; - for(final String bcExt: AbstractFeatureReader.BLOCK_COMPRESSED_EXTENSIONS) { + for(final String bcExt: IOUtil.BLOCK_COMPRESSED_EXTENSIONS) { Assert.assertTrue(codec.canDecode(String.format(pattern, "bed", bcExt))); Assert.assertFalse(codec.canDecode(String.format(pattern, "vcf", bcExt))); Assert.assertFalse(codec.canDecode(String.format(pattern, "bed.gzip", bcExt))); diff --git a/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java b/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java index 59038cf2a1..414e66358a 100644 --- a/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java +++ b/src/test/java/htsjdk/tribble/index/IndexFactoryTest.java @@ -209,8 +209,7 @@ public void testCreateLinearIndexFromBCF(final File inputBCF) throws IOException // we don't have an externally generated index file for the original input, so iterate through each variant // and use the generated index to query for the same variant in the indexed copy of the input final VariantContext vcOrig = originalIt.next(); - final Interval queryInterval = new Interval(vcOrig.getContig(), vcOrig.getStart(), vcOrig.getEnd()); - final Iterator tmpIt = tmpReader.query(queryInterval.getContig(), queryInterval.getStart(), queryInterval.getEnd()); + final Iterator tmpIt = tmpReader.query(vcOrig); Assert.assertTrue(tmpIt.hasNext(), "Variant not returned from indexed file"); final VariantContext vcTmp = tmpIt.next(); Assert.assertEquals(vcOrig.getContig(), vcTmp.getContig()); diff --git a/src/test/java/htsjdk/tribble/index/IndexTest.java b/src/test/java/htsjdk/tribble/index/IndexTest.java index 2764f2800e..61b8962533 100644 --- a/src/test/java/htsjdk/tribble/index/IndexTest.java +++ b/src/test/java/htsjdk/tribble/index/IndexTest.java @@ -19,6 +19,7 @@ import org.testng.annotations.Test; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.file.FileSystem; @@ -59,6 +60,13 @@ public void testMassiveQuery(final int start, final int mid, final int mid2, fin Assert.assertTrue(allSize >= Math.max(leftSize,rightSize), "Expected size of joint query " + allSize + " to be at least >= max of left " + leftSize + " and right queries " + rightSize); } + @Test() + public void testLoadFromStream() throws IOException { + LinearIndex index = (LinearIndex)IndexFactory.loadIndex(MassiveIndexFile.getAbsolutePath(), new FileInputStream(MassiveIndexFile)); + List sequenceNames = index.getSequenceNames(); + Assert.assertEquals(sequenceNames.size(), 1); + Assert.assertEquals(sequenceNames.get(0), CHR); + } @DataProvider(name = "writeIndexData") public Object[][] writeIndexData() { diff --git a/src/test/java/htsjdk/tribble/util/ParsingUtilsTest.java b/src/test/java/htsjdk/tribble/util/ParsingUtilsTest.java index c974790ddf..d6e5d62148 100644 --- a/src/test/java/htsjdk/tribble/util/ParsingUtilsTest.java +++ b/src/test/java/htsjdk/tribble/util/ParsingUtilsTest.java @@ -153,12 +153,12 @@ public void testInMemoryNioFileDoesNotExist() throws IOException{ tstExists(file.toUri().toString(), false); } - @Test + @Test(groups = "ftp") public void testFTPDoesExist() throws IOException{ tstExists(AVAILABLE_FTP_URL, true); } - @Test + @Test(groups = "ftp") public void testFTPNotExist() throws IOException{ tstExists(UNAVAILABLE_FTP_URL, false); } @@ -198,7 +198,7 @@ public void testInMemoryNioFileOpenInputStream() throws IOException{ tstStream(file.toUri().toString()); } - @Test + @Test(groups = "ftp") public void testFTPOpenInputStream() throws IOException{ tstStream(AVAILABLE_FTP_URL); } diff --git a/src/test/java/htsjdk/tribble/util/ftp/FTPClientTest.java b/src/test/java/htsjdk/tribble/util/ftp/FTPClientTest.java index 6b77f913ef..10a4236ff0 100644 --- a/src/test/java/htsjdk/tribble/util/ftp/FTPClientTest.java +++ b/src/test/java/htsjdk/tribble/util/ftp/FTPClientTest.java @@ -16,6 +16,7 @@ * @author Jim Robinson * @since 10/3/11 */ +@Test(groups="ftp") public class FTPClientTest extends HtsjdkTest { static String host = "ftp.broadinstitute.org"; diff --git a/src/test/java/htsjdk/tribble/util/ftp/FTPUtilsTest.java b/src/test/java/htsjdk/tribble/util/ftp/FTPUtilsTest.java index 87000ee143..a22a897ea0 100644 --- a/src/test/java/htsjdk/tribble/util/ftp/FTPUtilsTest.java +++ b/src/test/java/htsjdk/tribble/util/ftp/FTPUtilsTest.java @@ -15,7 +15,7 @@ */ public class FTPUtilsTest extends HtsjdkTest { - @Test + @Test(groups ="ftp") public void testResourceAvailable() throws Exception { URL goodUrl = new URL("ftp://ftp.broadinstitute.org/pub/igv/TEST/test.txt"); diff --git a/src/test/java/htsjdk/utils/ClassFinderTest.java b/src/test/java/htsjdk/utils/ClassFinderTest.java index e6f1a9e40d..6d34a053bf 100644 --- a/src/test/java/htsjdk/utils/ClassFinderTest.java +++ b/src/test/java/htsjdk/utils/ClassFinderTest.java @@ -1,7 +1,7 @@ package htsjdk.utils; import htsjdk.HtsjdkTest; -import org.junit.Assert; +import org.testng.Assert; import org.testng.annotations.Test; /** diff --git a/src/test/java/htsjdk/utils/TestNGUtils.java b/src/test/java/htsjdk/utils/TestNGUtils.java index cc7dd6c558..3eed34a788 100644 --- a/src/test/java/htsjdk/utils/TestNGUtils.java +++ b/src/test/java/htsjdk/utils/TestNGUtils.java @@ -1,11 +1,13 @@ package htsjdk.utils; +import com.google.common.collect.Lists; import org.testng.annotations.DataProvider; import org.testng.collections.Sets; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; +import java.util.stream.Collectors; /** * Small class implementing some utility functions that are useful for test and interfacing with the TestNG framework. @@ -40,4 +42,42 @@ public static Iterator getDataProviders(final String packageName) { return data.iterator(); } + + /** + * Combine two or more Dataproviders by taking the cartesian product of the their test cases. + * + * Note: In the case of a an empty provider, the result will be the product of the non-empty providers. + * This is different from the traditional definition of the cartesian product. + * @return the cartesian product of two or more DataProviders than can be used as a new dataprovider + */ + public static Object[][] cartesianProduct(Object[][]... dataProviders) { + List>> lists = Arrays.stream(dataProviders) + .map(TestNGUtils::nestedArraysToNestedLists) + .collect(Collectors.toList()); + final List>> product = Lists.cartesianProduct(lists); + final List> mergeProduct = product.stream() + .map( l -> l.stream() + .flatMap(Collection::stream) + .collect(Collectors.toList())) + .collect(Collectors.toList()); + return nestedListsToNestedArrays(mergeProduct); + } + + /** + * @param dataProvider a nested Object array + * @return an equivalent nested List + */ + public static List> nestedArraysToNestedLists(Object[][] dataProvider){ + return Arrays.stream(dataProvider) + .map(Arrays::asList) + .collect(Collectors.toList()); + } + + /** + * @param lists a nested List + * @return an equivalent nested array + */ + public static Object[][] nestedListsToNestedArrays(List> lists){ + return lists.stream().map(List::toArray).toArray(Object[][]::new); + } } diff --git a/src/test/java/htsjdk/utils/TestNGUtilsTest.java b/src/test/java/htsjdk/utils/TestNGUtilsTest.java new file mode 100644 index 0000000000..9fb811a7db --- /dev/null +++ b/src/test/java/htsjdk/utils/TestNGUtilsTest.java @@ -0,0 +1,150 @@ +package htsjdk.utils; + +import htsjdk.HtsjdkTest; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class TestNGUtilsTest extends HtsjdkTest { + + public static final Object[] EMPTY_ARRAY = new Object[0]; + + @DataProvider + public Object[][] getArraysAndLists() { + return new Object[][]{ + { + new Object[][]{ + {1, 2}, + {3, 4} + }, + Arrays.asList( + Arrays.asList(1, 2), + Arrays.asList(3, 4) + ) + }, + { + new Object[][]{ + {1} + }, + Arrays.asList( + Arrays.asList(1) + ) + }, + { + new Object[][]{ + {1, 2, 3}, + {4, 5, 6} + }, + Arrays.asList( + Arrays.asList(1, 2, 3), + Arrays.asList(4, 5, 6) + ) + }, + { + new Object[][]{ + {1}, + {2}, + {3}, + {4} + }, + Arrays.asList( + Arrays.asList(1), + Arrays.asList(2), + Arrays.asList(3), + Arrays.asList(4) + ) + }, + }; + } + + @Test(dataProvider = "getArraysAndLists") + public void testObjectsToLists(Object[][] objects, List> lists) { + Assert.assertEquals(TestNGUtils.nestedArraysToNestedLists(objects), lists); + } + + @Test(dataProvider = "getArraysAndLists") + public void testListsToArrays(Object[][] objects, List> lists) { + final Object[][] convertedObjects = TestNGUtils.nestedListsToNestedArrays(lists); + assertNestedArraysEqual(objects, convertedObjects); + } + + private static void assertNestedArraysEqual(Object[][] objects, Object[][] convertedObjects) { + for (int i = 0; i < objects.length; i++) { + Assert.assertEquals(convertedObjects[i], objects[i]); + } + } + + @DataProvider + public Object[][] getDataProviders() { + return new Object[][]{ + {new Object[][]{{1, 2}}, new Object[][]{{3}, {4}}, new Object[][]{{1, 2, 3}, {1, 2, 4}}}, + {new Object[][]{{1}}, new Object[][]{{2}}, new Object[][]{{1, 2}}}, + {new Object[][]{{1}}, new Object[][]{{2, 3}}, new Object[][]{{1, 2, 3}}}, + {new Object[][]{{1}, {2}, {3}}, new Object[][]{{'a', 'b'}, {'c', 'd'}}, + new Object[][]{{1, 'a', 'b'}, {1, 'c', 'd'}, + {2, 'a', 'b'}, {2, 'c', 'd'}, + {3, 'a', 'b'}, {3, 'c', 'd'}}}, + {new Object[][]{{}}, new Object[][]{{}}, new Object[][]{{}}}, + {new Object[][]{{}}, new Object[][]{{1}}, new Object[][]{{1}}}, + {new Object[][]{{}}, new Object[][]{{1, 2}}, new Object[][]{{1, 2}}}, + {new Object[][]{{1}}, new Object[][]{{}}, new Object[][]{{1}}}, + {new Object[][]{{}}, new Object[][]{{1}}, new Object[][]{{1}}}, + {new Object[][]{{EMPTY_ARRAY}}, new Object[][]{{1}}, new Object[][]{{EMPTY_ARRAY, 1}}}, + {new Object[][]{{1}, {2}, {3}}, new Object[][]{{4}, {5}, {6}}, + new Object[][]{{1,4}, {1,5}, {1,6}, {2, 4}, {2, 5}, {2, 6}, {3, 4}, {3, 5}, {3, 6}}} + }; + } + + @Test(dataProvider = "getDataProviders") + public void testProduct(Object[][] dataProvider1, Object[][] dataProvider2, Object[][] expectedResult) { + final Object[][] actual = TestNGUtils.cartesianProduct(dataProvider1, dataProvider2); + assertNestedArraysEqual(actual, expectedResult); + } + + + @DataProvider + public Object[][] getDifferingNumbersOfProviders() { + final Object[][] p1 = new Object[][]{{1}, {2}}; + final Object[][] p2 = new Object[][]{{"a", "b"}}; + final Object[][] p3 = new Object[][]{{}}; + final Object[][] p4 = new Object[][]{{3}, {4}, {5}}; + + final Object[][] expected0 = new Object[][]{{}}; + final Object[][] expected1 = new Object[][]{{1}, {2}}; + final Object[][] expected2 = new Object[][]{{1, "a", "b"}, {2, "a", "b"}}; + final Object[][] expected3 = expected2; + final Object[][] expected4 = new Object[][]{ + {1, "a", "b", 3}, + {1, "a", "b", 4}, + {1, "a", "b", 5}, + {2, "a", "b", 3}, + {2, "a", "b", 4}, + {2, "a", "b", 5} + }; + + return new Object[][]{ + {Arrays.asList(), expected0}, + {Collections.singletonList(p1), expected1}, + {Arrays.asList(p1, p2), expected2}, + {Arrays.asList(p1, p2, p3), expected3}, + {Arrays.asList(p1, p2, p3, p4), expected4} + }; + } + + @Test(dataProvider = "getDifferingNumbersOfProviders") + public void testCartesianProductOfManyProviders(List providers, Object[][] expected){ + final Object[][] product = TestNGUtils.cartesianProduct(providers.toArray(new Object[][][]{})); + assertNestedArraysEqual(product, expected); + } + + @Test + public void testSingleProvider() { + final Object[][] expected = {{1, 2}}; + final Object[][] product = TestNGUtils.cartesianProduct(expected); + assertNestedArraysEqual(product, expected); + } +} diff --git a/src/test/java/htsjdk/variant/utils/VCFHeaderReaderTest.java b/src/test/java/htsjdk/variant/utils/VCFHeaderReaderTest.java new file mode 100644 index 0000000000..cc2c5b7545 --- /dev/null +++ b/src/test/java/htsjdk/variant/utils/VCFHeaderReaderTest.java @@ -0,0 +1,46 @@ +package htsjdk.variant.utils; + +import htsjdk.HtsjdkTest; +import htsjdk.samtools.seekablestream.SeekableFileStream; +import htsjdk.tribble.TribbleException; +import htsjdk.variant.vcf.VCFHeader; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +public class VCFHeaderReaderTest extends HtsjdkTest { + @DataProvider(name = "files") + Object[][] pathsData() { + + final String TEST_DATA_DIR = "src/test/resources/htsjdk/variant/"; + return new Object[][]{ + {TEST_DATA_DIR + "VcfThatLacksAnIndex.bcf"}, + {TEST_DATA_DIR + "VcfThatLacksAnIndex.vcf"}, + {TEST_DATA_DIR + "VcfThatLacksAnIndex.vcf.bgz"}, + {TEST_DATA_DIR + "VcfThatLacksAnIndex.vcf.gz"}, + }; + } + + @Test(dataProvider = "files") + public void testReadHeaderFrom(final String file) throws IOException { + VCFHeader vcfHeader = VCFHeaderReader.readHeaderFrom(new SeekableFileStream(new File(file))); + Assert.assertNotNull(vcfHeader); + } + + @DataProvider + public Object[][] invalidFiles(){ + return new Object[][] { + { new File("src/test/resources/htsjdk/samtools/empty.bam")}, + {new File("src/test/resources/htsjdk/variant/corrupt_file_that_starts_with_#.vcf")} + }; + } + + @Test(dataProvider = "invalidFiles", expectedExceptions = TribbleException.InvalidHeader.class) + public void testReadHeaderForInvalidFile(File file) throws IOException { + VCFHeaderReader.readHeaderFrom(new SeekableFileStream(file)); + } +} diff --git a/src/test/java/htsjdk/variant/variantcontext/writer/VCFWriterUnitTest.java b/src/test/java/htsjdk/variant/variantcontext/writer/VCFWriterUnitTest.java index ff0a14c751..09b1f52c92 100644 --- a/src/test/java/htsjdk/variant/variantcontext/writer/VCFWriterUnitTest.java +++ b/src/test/java/htsjdk/variant/variantcontext/writer/VCFWriterUnitTest.java @@ -363,5 +363,25 @@ public void testModifyHeader() { Assert.assertNotNull(roundtripHeader.getOtherHeaderLine("FOOBAR"), "Could not find FOOBAR header line after a write/read cycle"); Assert.assertEquals(roundtripHeader.getOtherHeaderLine("FOOBAR").getValue(), "foovalue", "Wrong value for FOOBAR header line after a write/read cycle"); } + + + /** + * + * A test to check that we can't write VCF with missing header. + */ + @Test(dataProvider = "vcfExtensionsDataProvider", expectedExceptions = IllegalStateException.class) + public void testWriteWithEmptyHeader(final String extension) throws IOException { + final File fakeVCFFile = File.createTempFile("testWriteAndReadVCFHeaderless.", extension, tempDir); + metaData = new HashSet<>(); + additionalColumns = new HashSet<>(); + final SAMSequenceDictionary sequenceDict = createArtificialSequenceDictionary(); + final VCFHeader header = createFakeHeader(metaData, additionalColumns, sequenceDict); + try (final VariantContextWriter writer = new VariantContextWriterBuilder() + .setOutputFile(fakeVCFFile).setReferenceDictionary(sequenceDict) + .setOptions(EnumSet.of(Options.ALLOW_MISSING_FIELDS_IN_HEADER, Options.INDEX_ON_THE_FLY)) + .build()) { + writer.add(createVC(header)); + } + } } diff --git a/src/test/java/htsjdk/variant/variantcontext/writer/VariantContextWriterBuilderUnitTest.java b/src/test/java/htsjdk/variant/variantcontext/writer/VariantContextWriterBuilderUnitTest.java index cd0663642a..b412165319 100644 --- a/src/test/java/htsjdk/variant/variantcontext/writer/VariantContextWriterBuilderUnitTest.java +++ b/src/test/java/htsjdk/variant/variantcontext/writer/VariantContextWriterBuilderUnitTest.java @@ -1,43 +1,54 @@ /* -* Copyright (c) 2014 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. -*/ + * Copyright (c) 2014 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.variant.variantcontext.writer; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; import htsjdk.samtools.Defaults; import htsjdk.samtools.SAMSequenceDictionary; import htsjdk.samtools.util.BlockCompressedOutputStream; import htsjdk.samtools.util.IOUtil; -import htsjdk.samtools.util.RuntimeIOException; -import htsjdk.tribble.AbstractFeatureReader; import htsjdk.tribble.Tribble; import htsjdk.tribble.util.TabixUtils; import htsjdk.variant.VariantBaseTest; import htsjdk.variant.variantcontext.writer.VariantContextWriterBuilder.OutputType; -import htsjdk.variant.vcf.VCFUtils; +import htsjdk.variant.vcf.VCFHeader; +import java.nio.file.FileSystem; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Iterator; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; import org.testng.Assert; import org.testng.annotations.BeforeSuite; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.*; @@ -47,363 +58,521 @@ import java.util.List; public class VariantContextWriterBuilderUnitTest extends VariantBaseTest { - private static final String TEST_BASENAME = "htsjdk-test.VariantContextWriterBuilderUnitTest"; - private SAMSequenceDictionary dictionary; - - private File vcf; - private File vcfIdx; - private File vcfMD5; - private File bcf; - private File bcfIdx; - private File unknown; - - private List blockCompressedVCFs; - private List blockCompressedIndices; - - @BeforeSuite - public void before() throws IOException { - dictionary = createArtificialSequenceDictionary(); - vcf = File.createTempFile(TEST_BASENAME, IOUtil.VCF_FILE_EXTENSION); - vcf.deleteOnExit(); - vcfIdx = Tribble.indexFile(vcf); - vcfIdx.deleteOnExit(); - vcfMD5 = new File(vcf.getAbsolutePath() + ".md5"); - vcfMD5.deleteOnExit(); - bcf = File.createTempFile(TEST_BASENAME, IOUtil.BCF_FILE_EXTENSION); - bcf.deleteOnExit(); - bcfIdx = Tribble.indexFile(bcf); - bcfIdx.deleteOnExit(); - unknown = File.createTempFile(TEST_BASENAME, ".unknown"); - unknown.deleteOnExit(); - - blockCompressedVCFs = new ArrayList(); - blockCompressedIndices = new ArrayList(); - for (final String extension : AbstractFeatureReader.BLOCK_COMPRESSED_EXTENSIONS) { - final File blockCompressed = File.createTempFile(TEST_BASENAME, IOUtil.VCF_FILE_EXTENSION + extension); - blockCompressed.deleteOnExit(); - blockCompressedVCFs.add(blockCompressed); - - final File index = new File(blockCompressed.getAbsolutePath() + TabixUtils.STANDARD_INDEX_EXTENSION); - index.deleteOnExit(); - blockCompressedIndices.add(index); - } + private static final String TEST_BASENAME = "htsjdk-test VariantContextWriterBuilderUnitTest"; + private SAMSequenceDictionary dictionary; + + private File vcf; + private File vcfIdx; + private File vcfMD5; + private File bcf; + private File bcfIdx; + private File unknown; + + private List blockCompressedVCFs; + private List blockCompressedIndices; + + @BeforeSuite + public void before() throws IOException { + dictionary = createArtificialSequenceDictionary(); + vcf = File.createTempFile(TEST_BASENAME, IOUtil.VCF_FILE_EXTENSION); + vcf.deleteOnExit(); + vcfIdx = Tribble.indexFile(vcf); + vcfIdx.deleteOnExit(); + vcfMD5 = new File(vcf.getAbsolutePath() + ".md5"); + vcfMD5.deleteOnExit(); + bcf = File.createTempFile(TEST_BASENAME, IOUtil.BCF_FILE_EXTENSION); + bcf.deleteOnExit(); + bcfIdx = Tribble.indexFile(bcf); + bcfIdx.deleteOnExit(); + unknown = File.createTempFile(TEST_BASENAME, ".unknown"); + unknown.deleteOnExit(); + + blockCompressedVCFs = new ArrayList(); + blockCompressedIndices = new ArrayList(); + for (final String extension : IOUtil.BLOCK_COMPRESSED_EXTENSIONS) { + final File blockCompressed = File.createTempFile(TEST_BASENAME, IOUtil.VCF_FILE_EXTENSION + extension); + blockCompressed.deleteOnExit(); + blockCompressedVCFs.add(blockCompressed); + + final File index = new File(blockCompressed.getAbsolutePath() + TabixUtils.STANDARD_INDEX_EXTENSION); + index.deleteOnExit(); + blockCompressedIndices.add(index); } + } - @Test - public void testSetOutputFile() throws IOException { - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary); - - VariantContextWriter writer = builder.setOutputFile(vcf.getAbsolutePath()).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile VCF String"); - Assert.assertFalse(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFile VCF String was compressed"); + @Test + public void testSetOutputFile() throws IOException { + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary); - writer = builder.setOutputFile(vcf).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile VCF File"); - Assert.assertFalse(((VCFWriter)writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFile VCF File was compressed"); + VariantContextWriter writer = builder.setOutputFile(vcf.getAbsolutePath()).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile VCF String"); + Assert.assertFalse(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFile VCF String was compressed"); - for (final String extension : AbstractFeatureReader.BLOCK_COMPRESSED_EXTENSIONS) { - final File file = File.createTempFile(TEST_BASENAME + ".setoutput", extension); - file.deleteOnExit(); - final String filename = file.getAbsolutePath(); + writer = builder.setOutputFile(vcf).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile VCF File"); + Assert.assertFalse(((VCFWriter)writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFile VCF File was compressed"); - writer = builder.setOutputFile(filename).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile " + extension + " String"); - Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFile " + extension + " String was not compressed"); - - writer = builder.setOutputFile(file).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile " + extension + " File"); - Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFile " + extension + " File was not compressed"); - } - - writer = builder.setOutputFile(bcf).build(); - Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFile BCF String"); - - writer = builder.setOutputFile(bcf.getAbsolutePath()).build(); - Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFile BCF File"); - } + for (final String extension : IOUtil.BLOCK_COMPRESSED_EXTENSIONS) { + final File file = File.createTempFile(TEST_BASENAME + ".setoutput", extension); + file.deleteOnExit(); + final String filename = file.getAbsolutePath(); - @Test - public void testDetermineOutputType() { - Assert.assertEquals(OutputType.VCF, VariantContextWriterBuilder.determineOutputTypeFromFile(this.vcf)); - Assert.assertEquals(OutputType.BCF, VariantContextWriterBuilder.determineOutputTypeFromFile(this.bcf)); - Assert.assertEquals(OutputType.VCF_STREAM, VariantContextWriterBuilder.determineOutputTypeFromFile(new File("/dev/stdout"))); - for (final File f: this.blockCompressedVCFs) { - Assert.assertEquals(OutputType.BLOCK_COMPRESSED_VCF, VariantContextWriterBuilder.determineOutputTypeFromFile(f)); - } + writer = builder.setOutputFile(filename).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile " + extension + " String"); + Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFile " + extension + " String was not compressed"); - // Test symlinking - try { - final Path link = Files.createTempFile("foo.", ".tmp"); - Files.deleteIfExists(link); - Files.createSymbolicLink(link, this.vcf.toPath()); - link.toFile().deleteOnExit(); - Assert.assertEquals(OutputType.VCF, VariantContextWriterBuilder.determineOutputTypeFromFile(link.toFile())); - link.toFile().delete(); - } - catch (final IOException ioe) { - throw new RuntimeIOException(ioe); - } + writer = builder.setOutputFile(file).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile " + extension + " File"); + Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFile " + extension + " File was not compressed"); } - @Test - public void testSetOutputFileType() { - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputFile(unknown); - - VariantContextWriter writer = builder.setOutputFileType(VariantContextWriterBuilder.OutputType.VCF).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFileType VCF"); - Assert.assertFalse(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFileType VCF was compressed"); - - writer = builder.setOption(Options.FORCE_BCF).build(); - Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFileType FORCE_BCF set -> expected BCF, was VCF"); - - // test that FORCE_BCF remains in effect, overriding the explicit setting of VCF - writer = builder.setOutputFileType(VariantContextWriterBuilder.OutputType.VCF).build(); - Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFileType FORCE_BCF set 2 -> expected BCF, was VCF"); + writer = builder.setOutputFile(bcf).build(); + Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFile BCF String"); - writer = builder.unsetOption(Options.FORCE_BCF).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFileType FORCE_BCF unset -> expected VCF, was BCF"); - Assert.assertFalse(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFileType FORCE_BCF unset was compressed"); + writer = builder.setOutputFile(bcf.getAbsolutePath()).build(); + Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFile BCF File"); + } - writer = builder.setOutputFileType(VariantContextWriterBuilder.OutputType.BLOCK_COMPRESSED_VCF).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile BLOCK_COMPRESSED_VCF"); - Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFileType BLOCK_COMPRESSED_VCF was not compressed"); - writer = builder.setOutputFileType(VariantContextWriterBuilder.OutputType.BCF).build(); - Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFileType BCF"); + @DataProvider + public Iterator getFilesAndOutputTypes(){ + List cases = new ArrayList<>(); + cases.add(new Object[]{OutputType.VCF, this.vcf}); + cases.add(new Object[]{OutputType.BCF, this.bcf}); + cases.add(new Object[]{OutputType.VCF_STREAM, new File("/dev/stdout")}); + for (final File file: this.blockCompressedVCFs) { + cases.add( new Object[]{OutputType.BLOCK_COMPRESSED_VCF, file}); } - - @Test - public void testSetOutputStream() { - final OutputStream stream = new ByteArrayOutputStream(); - - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .unsetOption(Options.INDEX_ON_THE_FLY) - .setOutputStream(stream); - - VariantContextWriter writer = builder.build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputStream default"); - - writer = builder.setOption(Options.FORCE_BCF).build(); - Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputStream FORCE_BCF set -> expected BCF stream, was VCF stream"); - - // test that FORCE_BCF remains in effect, overriding the explicit setting of VCF - writer = builder.setOutputVCFStream(stream).build(); - Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputStream FORCE_BCF set 2 -> expected BCF stream, was VCF stream"); - - writer = builder.unsetOption(Options.FORCE_BCF).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputStream FORCE_BCF unset -> expected VCF stream, was BCF stream"); - - writer = builder.setOutputBCFStream(stream).build(); - Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputStream BCF"); - - writer = builder.setOutputVCFStream(stream).build(); - Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputStream VCF"); - } - - @Test - public void testAsync() { - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputFile(vcf); - - VariantContextWriter writer = builder.build(); - Assert.assertEquals(writer instanceof AsyncVariantContextWriter, Defaults.USE_ASYNC_IO_WRITE_FOR_TRIBBLE, "testAsync default"); - - writer = builder.setOption(Options.USE_ASYNC_IO).build(); - Assert.assertTrue(writer instanceof AsyncVariantContextWriter, "testAsync option=set"); - - writer = builder.unsetOption(Options.USE_ASYNC_IO).build(); - Assert.assertFalse(writer instanceof AsyncVariantContextWriter, "testAsync option=unset"); + return cases.iterator(); + } + + @Test(dataProvider = "getFilesAndOutputTypes") + public void testDetermineOutputType(OutputType expected, File file) { + Assert.assertEquals(VariantContextWriterBuilder.determineOutputTypeFromFile(file), expected); + } + + @Test(dataProvider = "getFilesAndOutputTypes") + public void testDetermineOutputTypeWithSymlink(OutputType expected, File file) throws IOException { + final File link = setUpSymlink(file); + Assert.assertEquals(expected, VariantContextWriterBuilder.determineOutputTypeFromFile(link)); + } + + @Test(dataProvider = "getFilesAndOutputTypes") + public void testDetermineOutputTypeOnPath(OutputType expected, File file) { + Assert.assertEquals(VariantContextWriterBuilder.determineOutputTypeFromFile(file.toPath()), expected); + } + + @Test(dataProvider = "getFilesAndOutputTypes") + public void testDetermineOutputTypeWithSymlinkOnPath(OutputType expected, File file) throws IOException { + final File link = setUpSymlink(file); + Assert.assertEquals(expected, VariantContextWriterBuilder.determineOutputTypeFromFile(link.toPath())); + } + + private static File setUpSymlink(File target) throws IOException { + final Path link = Files.createTempFile("foo.", ".tmp"); + Files.deleteIfExists(link); + Files.createSymbolicLink(link, target.toPath()); + link.toFile().deleteOnExit(); + return link.toFile(); + } + + @Test + public void testSetOutputFileType() { + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputFile(unknown); + + VariantContextWriter writer = builder.setOutputFileType(VariantContextWriterBuilder.OutputType.VCF).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFileType VCF"); + Assert.assertFalse(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFileType VCF was compressed"); + + writer = builder.setOption(Options.FORCE_BCF).build(); + Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFileType FORCE_BCF set -> expected BCF, was VCF"); + + // test that FORCE_BCF remains in effect, overriding the explicit setting of VCF + writer = builder.setOutputFileType(VariantContextWriterBuilder.OutputType.VCF).build(); + Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFileType FORCE_BCF set 2 -> expected BCF, was VCF"); + + writer = builder.unsetOption(Options.FORCE_BCF).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFileType FORCE_BCF unset -> expected VCF, was BCF"); + Assert.assertFalse(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFileType FORCE_BCF unset was compressed"); + + writer = builder.setOutputFileType(VariantContextWriterBuilder.OutputType.BLOCK_COMPRESSED_VCF).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputFile BLOCK_COMPRESSED_VCF"); + Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BlockCompressedOutputStream, "testSetOutputFileType BLOCK_COMPRESSED_VCF was not compressed"); + + writer = builder.setOutputFileType(VariantContextWriterBuilder.OutputType.BCF).build(); + Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputFileType BCF"); + } + + @Test + public void testSetOutputStream() { + final OutputStream stream = new ByteArrayOutputStream(); + + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .unsetOption(Options.INDEX_ON_THE_FLY) + .setOutputStream(stream); + + VariantContextWriter writer = builder.build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputStream default"); + + writer = builder.setOption(Options.FORCE_BCF).build(); + Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputStream FORCE_BCF set -> expected BCF stream, was VCF stream"); + + // test that FORCE_BCF remains in effect, overriding the explicit setting of VCF + writer = builder.setOutputVCFStream(stream).build(); + Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputStream FORCE_BCF set 2 -> expected BCF stream, was VCF stream"); + + writer = builder.unsetOption(Options.FORCE_BCF).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputStream FORCE_BCF unset -> expected VCF stream, was BCF stream"); + + writer = builder.setOutputBCFStream(stream).build(); + Assert.assertTrue(writer instanceof BCF2Writer, "testSetOutputStream BCF"); + + writer = builder.setOutputVCFStream(stream).build(); + Assert.assertTrue(writer instanceof VCFWriter, "testSetOutputStream VCF"); + } + + @Test + public void testAsync() { + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputFile(vcf); + + VariantContextWriter writer = builder.build(); + Assert.assertEquals(writer instanceof AsyncVariantContextWriter, Defaults.USE_ASYNC_IO_WRITE_FOR_TRIBBLE, "testAsync default"); + + writer = builder.setOption(Options.USE_ASYNC_IO).build(); + Assert.assertTrue(writer instanceof AsyncVariantContextWriter, "testAsync option=set"); + + writer = builder.unsetOption(Options.USE_ASYNC_IO).build(); + Assert.assertFalse(writer instanceof AsyncVariantContextWriter, "testAsync option=unset"); + } + + @Test + public void testBuffering() { + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputFile(vcf) + .unsetOption(Options.INDEX_ON_THE_FLY); // so the potential BufferedOutputStream is not wrapped in a PositionalOutputStream + + VariantContextWriter writer = builder.build(); + Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BufferedOutputStream, "testBuffering was not buffered by default"); + + writer = builder.unsetBuffering().build(); + Assert.assertFalse(((VCFWriter) writer).getOutputStream() instanceof BufferedOutputStream, "testBuffering was buffered when unset"); + + writer = builder.setBuffer(8192).build(); + Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BufferedOutputStream, "testBuffering was not buffered when set"); + } + + @Test + public void testMD5() { + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputFile(vcf); + + VariantContextWriter writer = builder.build(); + writer.close(); + Assert.assertEquals(vcfMD5.exists(), Defaults.CREATE_MD5, "MD5 default setting not respected"); + + if (vcfMD5.exists()) + vcfMD5.delete(); + + writer = builder.setCreateMD5().build(); + writer.close(); + Assert.assertTrue(vcfMD5.exists(), "MD5 not created when requested"); + vcfMD5.delete(); + + writer = builder.unsetCreateMD5().build(); + writer.close(); + Assert.assertFalse(vcfMD5.exists(), "MD5 created when not requested"); + + writer = builder.setCreateMD5(false).build(); + writer.close(); + Assert.assertFalse(vcfMD5.exists(), "MD5 created when not requested via boolean parameter"); + + writer = builder.setCreateMD5(true).build(); + writer.close(); + Assert.assertTrue(vcfMD5.exists(), "MD5 not created when requested via boolean parameter"); + vcfMD5.delete(); + + for (final File blockCompressed : blockCompressedVCFs) { + final File md5 = new File(blockCompressed + ".md5"); + if (md5.exists()) + md5.delete(); + md5.deleteOnExit(); + writer = builder.setOutputFile(blockCompressed).build(); + writer.close(); + Assert.assertTrue(md5.exists(), "MD5 digest not created for " + blockCompressed); } - - @Test - public void testBuffering() { - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputFile(vcf) - .unsetOption(Options.INDEX_ON_THE_FLY); // so the potential BufferedOutputStream is not wrapped in a PositionalOutputStream - - VariantContextWriter writer = builder.build(); - Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BufferedOutputStream, "testBuffering was not buffered by default"); - - writer = builder.unsetBuffering().build(); - Assert.assertFalse(((VCFWriter) writer).getOutputStream() instanceof BufferedOutputStream, "testBuffering was buffered when unset"); - - writer = builder.setBuffer(8192).build(); - Assert.assertTrue(((VCFWriter) writer).getOutputStream() instanceof BufferedOutputStream, "testBuffering was not buffered when set"); + } + + @Test + public void testIndexingOnTheFly() { + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOption(Options.INDEX_ON_THE_FLY); + + if (vcfIdx.exists()) + vcfIdx.delete(); + VariantContextWriter writer = builder.setOutputFile(vcf).build(); + writer.close(); + Assert.assertTrue(vcfIdx.exists(), String.format("VCF index not created for %s / %s", vcf, vcfIdx)); + + if (bcfIdx.exists()) + bcfIdx.delete(); + writer = builder.setOutputFile(bcf).build(); + writer.close(); + Assert.assertTrue(bcfIdx.exists(), String.format("BCF index not created for %s / %s", bcf, bcfIdx)); + + for (int i = 0; i < blockCompressedVCFs.size(); i++) { + final File blockCompressed = blockCompressedVCFs.get(i); + final File index = blockCompressedIndices.get(i); + if (index.exists()) + index.delete(); + writer = builder.setOutputFile(blockCompressed).setReferenceDictionary(dictionary).build(); + writer.close(); + Assert.assertTrue(index.exists(), String.format("Block-compressed index not created for %s / %s", blockCompressed, index)); + + // Tabix does not require a reference dictionary. + // Tribble does: see tests testRefDictRequiredForVCFIndexOnTheFly / testRefDictRequiredForBCFIndexOnTheFly + + index.delete(); + writer = builder.setReferenceDictionary(null).build(); + writer.close(); + Assert.assertTrue(index.exists(), String.format("Block-compressed index not created for %s / %s", blockCompressed, index)); } - - @Test - public void testMD5() { - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputFile(vcf); - - VariantContextWriter writer = builder.build(); - writer.close(); - Assert.assertEquals(vcfMD5.exists(), Defaults.CREATE_MD5, "MD5 default setting not respected"); - - if (vcfMD5.exists()) - vcfMD5.delete(); - - writer = builder.setCreateMD5().build(); - writer.close(); - Assert.assertTrue(vcfMD5.exists(), "MD5 not created when requested"); - vcfMD5.delete(); - - writer = builder.unsetCreateMD5().build(); - writer.close(); - Assert.assertFalse(vcfMD5.exists(), "MD5 created when not requested"); - - writer = builder.setCreateMD5(false).build(); - writer.close(); - Assert.assertFalse(vcfMD5.exists(), "MD5 created when not requested via boolean parameter"); - - writer = builder.setCreateMD5(true).build(); - writer.close(); - Assert.assertTrue(vcfMD5.exists(), "MD5 not created when requested via boolean parameter"); - vcfMD5.delete(); - - for (final File blockCompressed : blockCompressedVCFs) { - final File md5 = new File(blockCompressed + ".md5"); - if (md5.exists()) - md5.delete(); - md5.deleteOnExit(); - writer = builder.setOutputFile(blockCompressed).build(); - writer.close(); - Assert.assertTrue(md5.exists(), "MD5 digest not created for " + blockCompressed); + } + + @Test + public void testIndexingOnTheFlyForPath() throws IOException { + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOption(Options.INDEX_ON_THE_FLY); + + try (FileSystem fs = Jimfs.newFileSystem("test", Configuration.unix())) { + final Path vcfPath = fs.getPath(vcf.getName()); + final Path vcfIdxPath = Tribble.indexPath(vcfPath); + try(final VariantContextWriter writer = builder.setOutputPath(vcfPath).build()) + { + //deliberately empty + } + + Assert.assertTrue(Files.exists(vcfIdxPath), + String.format("VCF index not created for %s / %s", vcfPath, vcfIdxPath)); + + final Path bcfPath = fs.getPath(bcf.getName()); + final Path bcfIdxPath = Tribble.indexPath(bcfPath); + try(final VariantContextWriter writer = builder.setOutputPath(bcfPath).build()){ + //deliberately empty + } + Assert.assertTrue(Files.exists(bcfIdxPath), + String.format("BCF index not created for %s / %s", bcfPath, bcfIdxPath)); + + for (int i = 0; i < blockCompressedVCFs.size(); i++) { + final File blockCompressed = blockCompressedVCFs.get(i); + final File index = blockCompressedIndices.get(i); + + final Path blockCompressedPath = fs.getPath(blockCompressed.getName()); + final Path indexPath = fs.getPath(index.getName()); + + Assert.assertFalse(Files.exists(indexPath)); + try(VariantContextWriter writer = builder.setOutputPath(blockCompressedPath).setReferenceDictionary(dictionary).build()){ + //deliberately empty } - } - - @Test - public void testIndexingOnTheFly() { - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOption(Options.INDEX_ON_THE_FLY); - - if (vcfIdx.exists()) - vcfIdx.delete(); - VariantContextWriter writer = builder.setOutputFile(vcf).build(); - writer.close(); - Assert.assertTrue(vcfIdx.exists(), String.format("VCF index not created for %s / %s", vcf, vcfIdx)); - - if (bcfIdx.exists()) - bcfIdx.delete(); - writer = builder.setOutputFile(bcf).build(); - writer.close(); - Assert.assertTrue(bcfIdx.exists(), String.format("BCF index not created for %s / %s", bcf, bcfIdx)); - - for (int i = 0; i < blockCompressedVCFs.size(); i++) { - final File blockCompressed = blockCompressedVCFs.get(i); - final File index = blockCompressedIndices.get(i); - if (index.exists()) - index.delete(); - writer = builder.setOutputFile(blockCompressed).setReferenceDictionary(dictionary).build(); - writer.close(); - Assert.assertTrue(index.exists(), String.format("Block-compressed index not created for %s / %s", blockCompressed, index)); - - // Tabix does not require a reference dictionary. - // Tribble does: see tests testRefDictRequiredForVCFIndexOnTheFly / testRefDictRequiredForBCFIndexOnTheFly - - index.delete(); - writer = builder.setReferenceDictionary(null).build(); - writer.close(); - Assert.assertTrue(index.exists(), String.format("Block-compressed index not created for %s / %s", blockCompressed, index)); + Assert.assertTrue(Files.exists(indexPath), String + .format("Block-compressed index not created for %s / %s", blockCompressedPath, indexPath)); + + // Tabix does not require a reference dictionary. + // Tribble does: see tests testRefDictRequiredForVCFIndexOnTheFly / testRefDictRequiredForBCFIndexOnTheFly + Files.delete(indexPath); + try (VariantContextWriter writer = builder.setReferenceDictionary(null).build()){ + //deliberately empty } + Assert.assertTrue(Files.exists(indexPath), String + .format("Block-compressed index not created for %s / %s", blockCompressedPath, indexPath)); + } } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testInvalidImplicitFileType() { - new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputFile("test.bam") - .build(); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testSetInvalidFileType() { - new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputFile("test.bam") - .setOutputFileType(VariantContextWriterBuilder.OutputType.VCF_STREAM) - .build(); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testInvalidSetFileTypeForStream() { - new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputStream(new ByteArrayOutputStream()) - .setOutputFileType(VariantContextWriterBuilder.OutputType.VCF) - .build(); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testUnsupportedIndexOnTheFlyForStreaming() { - new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputStream(new ByteArrayOutputStream()) - .setOption(Options.INDEX_ON_THE_FLY) - .build(); + } + + @Test(singleThreaded = true, groups = "unix") + public void testWriteToFifo() throws IOException, InterruptedException, ExecutionException { + long length = testWriteToPipe(this::innerWriteToFifo); + // length>0 means we wrote to the named pipe, so all is well. + Assert.assertTrue(length>0, + "VariantContextWriterBuilder did not write to the named pipe as it should."); + } + + private void innerWriteToFifo(String pathToFifo) { + // Do not enable INDEX_OF_THE_FLY because that is not compatible with writing to a pipe. + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder() + .clearOptions() + .setReferenceDictionary(dictionary); + + Path vcfPath = Paths.get(pathToFifo); + VariantContextWriter writer = builder.setOutputPath(vcfPath).build(); + writer.writeHeader(new VCFHeader()); + writer.close(); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testInvalidImplicitFileType() { + new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputFile("test.bam") + .build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testSetInvalidFileType() { + new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputFile("test.bam") + .setOutputFileType(VariantContextWriterBuilder.OutputType.VCF_STREAM) + .build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testInvalidSetFileTypeForStream() { + new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputStream(new ByteArrayOutputStream()) + .setOutputFileType(VariantContextWriterBuilder.OutputType.VCF) + .build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testUnsupportedIndexOnTheFlyForStreaming() { + new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputStream(new ByteArrayOutputStream()) + .setOption(Options.INDEX_ON_THE_FLY) + .build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testUnsupportedDefaultIndexOnTheFlyForStreaming() { + new VariantContextWriterBuilder() + .setReferenceDictionary(dictionary) + .setOutputStream(new ByteArrayOutputStream()) + .build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testRefDictRequiredForVCFIndexOnTheFly() { + new VariantContextWriterBuilder() + .setOutputFile(vcf) + .setOption(Options.INDEX_ON_THE_FLY) + .build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testRefDictRequiredForBCFIndexOnTheFly() { + new VariantContextWriterBuilder() + .setOutputFile(bcf) + .setOption(Options.INDEX_ON_THE_FLY) + .build(); + } + + @Test + public void testClearOptions() { + // Verify that clearOptions doesn't have a side effect of carrying previously set options + // forward to subsequent builders + VariantContextWriterBuilder vcwb = new VariantContextWriterBuilder(); + vcwb.clearOptions().setOption(Options.INDEX_ON_THE_FLY); + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder().clearOptions(); + Assert.assertTrue(builder.options.isEmpty()); + } + + @Test + public void testModifyOption() { + final VariantContextWriterBuilder builder = new VariantContextWriterBuilder().clearOptions(); + for (final Options option : Options.values()) { + Assert.assertFalse(builder.isOptionSet(option)); // shouldn't be set + builder.modifyOption(option, false); + Assert.assertFalse(builder.isOptionSet(option)); // still shouldn't be set + builder.modifyOption(option, true); + Assert.assertTrue(builder.isOptionSet(option)); // now is set + builder.modifyOption(option, false); + Assert.assertFalse(builder.isOptionSet(option)); // has been unset } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testUnsupportedDefaultIndexOnTheFlyForStreaming() { - new VariantContextWriterBuilder() - .setReferenceDictionary(dictionary) - .setOutputStream(new ByteArrayOutputStream()) - .build(); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testRefDictRequiredForVCFIndexOnTheFly() { - new VariantContextWriterBuilder() - .setOutputFile(vcf) - .setOption(Options.INDEX_ON_THE_FLY) - .build(); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testRefDictRequiredForBCFIndexOnTheFly() { - new VariantContextWriterBuilder() - .setOutputFile(bcf) - .setOption(Options.INDEX_ON_THE_FLY) - .build(); - } - - @Test - public void testClearOptions() { - // Verify that clearOptions doesn't have a side effect of carrying previously set options - // forward to subsequent builders - VariantContextWriterBuilder vcwb = new VariantContextWriterBuilder(); - vcwb.clearOptions().setOption(Options.INDEX_ON_THE_FLY); - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder().clearOptions(); - Assert.assertTrue(builder.options.isEmpty()); - } - - @Test - public void testModifyOption() { - final VariantContextWriterBuilder builder = new VariantContextWriterBuilder().clearOptions(); - for (final Options option : Options.values()) { - Assert.assertFalse(builder.isOptionSet(option)); // shouldn't be set - builder.modifyOption(option, false); - Assert.assertFalse(builder.isOptionSet(option)); // still shouldn't be set - builder.modifyOption(option, true); - Assert.assertTrue(builder.isOptionSet(option)); // now is set - builder.modifyOption(option, false); - Assert.assertFalse(builder.isOptionSet(option)); // has been unset + } + + @Test + public void testStdOut() { + final VariantContextWriter writer = new VariantContextWriterBuilder().setOutputFile("/dev/stdout").clearOptions().build(); + OutputStream s = ((VCFWriter) writer).getOutputStream(); + Assert.assertNotNull(((VCFWriter) writer).getOutputStream()); + Assert.assertNotEquals(((VCFWriter) writer).getStreamName(), IndexingVariantContextWriter.DEFAULT_READER_NAME); + } + + @Test(expectedExceptions = java.util.concurrent.ExecutionException.class) + public void demonstrateTestWriteToPipeDoesNotHang_1() throws Exception { + testWriteToPipe((str) -> { + throw new RuntimeException("oops"); + }); + } + + @Test(expectedExceptions = java.util.concurrent.ExecutionException.class) + public void demonstrateTestWriteToPipeDoesNotHang_2() throws Exception { + long x = testWriteToPipe((str) -> {try{Files.write(Paths.get(str), "hello world".getBytes());}catch(IOException ex){}; throw new RuntimeException("oops");}); + } + + + /** + * Create a named pipe, call "codeThatWritesToAFilename" with the name as argument, + * consumes the output as it's being run and returns the number of bytes that were output. + * + * This only works on Unix. Use this decoration for the tests that use it: + * @Test(singleThreaded = true, groups = "unix") + */ + private static long testWriteToPipe(final Consumer codeThatWritesToAFilename) throws IOException, InterruptedException, ExecutionException { + final File fifo = makeFifo(); + + // run the code in a separate thread + ExecutorService executor = Executors.newFixedThreadPool(2); + try { + final Future writeResult = executor.submit(() -> { + try { + codeThatWritesToAFilename.accept(fifo.getAbsolutePath()); + } catch (Exception x) { + // Print to the console to aid debugging, in case the exception doesn't surface. + x.printStackTrace(); + throw(x); } - } + }); + + // drain the pipe with the output. + final Future readResult = executor.submit(() -> { + try(final InputStream inputStream = Files.newInputStream(fifo.toPath(), StandardOpenOption.READ)) { + int count = 0; + while (inputStream.read() >= 0) { + count++; + } + return count; + } + }); - @Test - public void testStdOut() { - final VariantContextWriter writer = new VariantContextWriterBuilder().setOutputFile("/dev/stdout").clearOptions().build(); - OutputStream s = ((VCFWriter) writer).getOutputStream(); - Assert.assertNotNull(((VCFWriter) writer).getOutputStream()); - Assert.assertNotEquals(((VCFWriter) writer).getStreamName(), IndexingVariantContextWriter.DEFAULT_READER_NAME); + // done. If it was in error, the line below will throw the exception. + writeResult.get(); + return readResult.get(); + } finally { + executor.shutdownNow(); } + } + + private static File makeFifo() throws IOException, InterruptedException { + // make the fifo + final File fifo = File.createTempFile("fifo.for.testWriteToPipe", ""); + Assert.assertTrue(fifo.delete()); + fifo.deleteOnExit(); + final Process exec = new ProcessBuilder("mkfifo", fifo.getAbsolutePath()).start(); + exec.waitFor(1, TimeUnit.MINUTES); + Assert.assertEquals(exec.exitValue(), 0, "mkfifo failed with exit code " + 0); + return fifo; + } + } diff --git a/src/test/java/htsjdk/variant/vcf/AbstractVCFCodecTest.java b/src/test/java/htsjdk/variant/vcf/AbstractVCFCodecTest.java index 9f81547ed2..78a3c63160 100644 --- a/src/test/java/htsjdk/variant/vcf/AbstractVCFCodecTest.java +++ b/src/test/java/htsjdk/variant/vcf/AbstractVCFCodecTest.java @@ -12,49 +12,58 @@ import java.io.File; import java.util.List; +public class AbstractVCFCodecTest extends VariantBaseTest { + @Test + public void shouldPreserveSymbolicAlleleCase() { + final VariantContext variant; + try (final VCFFileReader reader = new VCFFileReader(new File(VariantBaseTest.variantTestDataRoot + "breakpoint.vcf"), false)) { + variant = reader.iterator().next(); -public class AbstractVCFCodecTest extends VariantBaseTest { + } + // VCF v4.1 s1.4.5 + // Tools processing VCF files are not required to preserve case in the allele String, except for IDs, which are case sensitive. + Assert.assertTrue(variant.getAlternateAllele(0).getDisplayString().contains("chr12")); + } + + @Test + public void TestSpanDelParseAlleles() { + final List list = VCF3Codec.parseAlleles("A", Allele.SPAN_DEL_STRING, 0); + } + + @Test(expectedExceptions = TribbleException.class) + public void TestSpanDelParseAllelesException() { + final List list1 = VCF3Codec.parseAlleles(Allele.SPAN_DEL_STRING, "A", 0); + } + + @DataProvider(name = "thingsToTryToDecode") + public Object[][] getThingsToTryToDecode() { + return new Object[][]{ + {"src/test/resources/htsjdk/tribble/tabix/testTabixIndex.vcf", true}, + {"src/test/resources/htsjdk/tribble/tabix/testTabixIndex.vcf.gz", true}, + {"src/test/resources/htsjdk/tribble/nonexistant.garbage", false}, + {"src/test/resources/htsjdk/tribble/testIntervalList.list", false} + }; + } + + @Test(dataProvider = "thingsToTryToDecode") + public void testCanDecodeFile(String potentialInput, boolean canDecode) { + Assert.assertEquals(AbstractVCFCodec.canDecodeFile(potentialInput, VCFCodec.VCF4_MAGIC_HEADER), canDecode); + } + + @Test + public void testGetTabixFormat() { + Assert.assertEquals(new VCFCodec().getTabixFormat(), TabixFormat.VCF); + Assert.assertEquals(new VCF3Codec().getTabixFormat(), TabixFormat.VCF); + } - @Test - public void shouldPreserveSymbolicAlleleCase() { - VCFFileReader reader = new VCFFileReader(new File(VariantBaseTest.variantTestDataRoot + "breakpoint.vcf"), false); - VariantContext variant = reader.iterator().next(); - reader.close(); - - // VCF v4.1 s1.4.5 - // Tools processing VCF files are not required to preserve case in the allele String, except for IDs, which are case sensitive. - Assert.assertTrue(variant.getAlternateAllele(0).getDisplayString().contains("chr12")); - } - - @Test - public void TestSpanDelParseAlleles(){ - List list = VCF3Codec.parseAlleles("A", Allele.SPAN_DEL_STRING, 0); - } - - @Test(expectedExceptions = TribbleException.class) - public void TestSpanDelParseAllelesException(){ - List list1 = VCF3Codec.parseAlleles(Allele.SPAN_DEL_STRING, "A", 0); - } - - @DataProvider(name="thingsToTryToDecode") - public Object[][] getThingsToTryToDecode(){ - return new Object[][] { - {"src/test/resources/htsjdk/tribble/tabix/testTabixIndex.vcf", true}, - {"src/test/resources/htsjdk/tribble/tabix/testTabixIndex.vcf.gz", true}, - {"src/test/resources/htsjdk/tribble/nonexistant.garbage", false}, - {"src/test/resources/htsjdk/tribble/testIntervalList.list", false} - }; - } - - @Test(dataProvider = "thingsToTryToDecode") - public void testCanDecodeFile(String potentialInput, boolean canDecode) { - Assert.assertEquals(AbstractVCFCodec.canDecodeFile(potentialInput, VCFCodec.VCF4_MAGIC_HEADER), canDecode); - } - - @Test - public void testGetTabixFormat() { - Assert.assertEquals(new VCFCodec().getTabixFormat(), TabixFormat.VCF); - Assert.assertEquals(new VCF3Codec().getTabixFormat(), TabixFormat.VCF); - } + @Test + public void testGLnotOverridePL() { + final VariantContext variant; + try (final VCFFileReader reader = new VCFFileReader( + new File("src/test/resources/htsjdk/variant/test_withGLandPL.vcf"), false)) { + variant = reader.iterator().next(); + } + Assert.assertEquals(variant.getGenotype(0).getPL(), new int[]{45, 0, 50}); + } } diff --git a/src/test/java/htsjdk/variant/vcf/VCFHeaderLineUnitTest.java b/src/test/java/htsjdk/variant/vcf/VCFHeaderLineUnitTest.java index 02cde53109..e04d3c69c8 100644 --- a/src/test/java/htsjdk/variant/vcf/VCFHeaderLineUnitTest.java +++ b/src/test/java/htsjdk/variant/vcf/VCFHeaderLineUnitTest.java @@ -25,7 +25,6 @@ public void testEncodeVCFHeaderLineWithUnescapedQuotes() { assertEquals(encodedAttributes, expectedEncoding); } - @Test public void testEncodeVCFHeaderLineWithEscapedQuotes() { @@ -40,4 +39,28 @@ public void testEncodeVCFHeaderLineWithEscapedQuotes() { assertEquals(encodedAttributes, expectedEncoding); } + @Test(expectedExceptions = { IllegalArgumentException.class }, expectedExceptionsMessageRegExp = "Invalid count number, with fixed count the number should be 1 or higher: .*") + public void testFormatNumberExeptions() { + new VCFFormatHeaderLine("test", + 0, + VCFHeaderLineType.Integer, + ""); + } + + @Test(expectedExceptions = { IllegalArgumentException.class }, expectedExceptionsMessageRegExp = "Invalid count number, with fixed count the number should be 1 or higher: .*") + public void testInfoNumberExeptions() { + new VCFInfoHeaderLine("test", + 0, + VCFHeaderLineType.Integer, + ""); + } + + @Test + public void testNumberExceptionFlag() { + // Should not raise an exception + new VCFInfoHeaderLine("test", + 0, + VCFHeaderLineType.Flag, + ""); + } } diff --git a/src/test/resources/htsjdk/samtools/BAMCigarOverflowTest/cigar-64k.sam.gz b/src/test/resources/htsjdk/samtools/BAMCigarOverflowTest/cigar-64k.sam.gz new file mode 100644 index 0000000000..fe46bbe058 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/BAMCigarOverflowTest/cigar-64k.sam.gz differ diff --git a/src/test/resources/htsjdk/samtools/cram/c2#pad.2.1.cram b/src/test/resources/htsjdk/samtools/cram/c2#pad.2.1.cram index 12ce718fd2..00c103b42a 100644 Binary files a/src/test/resources/htsjdk/samtools/cram/c2#pad.2.1.cram and b/src/test/resources/htsjdk/samtools/cram/c2#pad.2.1.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/c2#pad.3.0.cram b/src/test/resources/htsjdk/samtools/cram/c2#pad.3.0.cram index e069a6b5f8..541e1e00ac 100644 Binary files a/src/test/resources/htsjdk/samtools/cram/c2#pad.3.0.cram and b/src/test/resources/htsjdk/samtools/cram/c2#pad.3.0.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/c2#pad.sam b/src/test/resources/htsjdk/samtools/cram/c2#pad.sam new file mode 100644 index 0000000000..49e991b258 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/c2#pad.sam @@ -0,0 +1,26 @@ +@SQ SN:c2 LN:9 +@CO +@CO mpileup example from https://github.com/samtools/htslib/issues/59 +@CO with additional Pad cigar operations +@CO +@CO c2 CC***AA**T**AA***CC +@CO +@CO +s1 CT***AA**T**AA***TC +@CO +s1b CT*******T*******TC +@CO +s2 CT*****G***G*****TC +@CO +s2p CT*****G***G*****TC +@CO +s3 CT*****GG*GG*****TC +@CO +s3b CT****CGGCGGC****TC +@CO +s4 CT***AAG***GAA***TC +@CO +s4p CT***AAG***GAA***TC +@CO +s5 CTGGG*********GGGTC +@CO +s1 0 c2 1 0 9M * 0 0 CTAATAATC XXXXXXXXX +s1b 0 c2 1 0 2M2D1M2D2M * 0 0 CTTTC * +s2 0 c2 1 0 2M2D1I1D1I2D2M * 0 0 CTGGTC * +s2p 0 c2 1 0 2M2D1I1P1D1P1I2D2M * 0 0 CTGGTC * +s3 0 c2 1 0 2M2D2I1D2I2D2M * 0 0 CTGGGGTC * +s3b 0 c2 1 0 2M1D1M2I1M2I1M1D2M * 0 0 CTCGGCGGCTC * +s4 0 c2 1 0 4M1I1D1I4M * 0 0 CTAAGGAATC * +s4p 0 c2 1 0 4M1I1P1D1P1I4M * 0 0 CTAAGGAATC * +s5 0 c2 1 0 2M3I5D3I2M * 0 0 CTGGGGGGTC * diff --git a/src/test/resources/htsjdk/samtools/cram/c2.fa b/src/test/resources/htsjdk/samtools/cram/c2.fa new file mode 100644 index 0000000000..1e1d309a15 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/c2.fa @@ -0,0 +1,2 @@ +>c2 +CCAATAACC diff --git a/src/test/resources/htsjdk/samtools/cram/c2.fa.fai b/src/test/resources/htsjdk/samtools/cram/c2.fa.fai new file mode 100644 index 0000000000..f95d35d9da --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/c2.fa.fai @@ -0,0 +1 @@ +c2 9 4 9 10 diff --git a/src/test/resources/htsjdk/samtools/cram/ce#1000.2.1.cram b/src/test/resources/htsjdk/samtools/cram/ce#1000.2.1.cram new file mode 100644 index 0000000000..2f51131a27 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/cram/ce#1000.2.1.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/ce#1000.3.0.cram b/src/test/resources/htsjdk/samtools/cram/ce#1000.3.0.cram new file mode 100644 index 0000000000..65d991f03d Binary files /dev/null and b/src/test/resources/htsjdk/samtools/cram/ce#1000.3.0.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/ce#1000.sam b/src/test/resources/htsjdk/samtools/cram/ce#1000.sam new file mode 100644 index 0000000000..857a9cd8eb --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/ce#1000.sam @@ -0,0 +1,1005 @@ +@SQ SN:CHROMOSOME_I LN:1009800 +@SQ SN:CHROMOSOME_II LN:5000 +@SQ SN:CHROMOSOME_III LN:5000 +@SQ SN:CHROMOSOME_IV LN:5000 +@SQ SN:CHROMOSOME_V LN:5000 +SRR065390.14978392 16 CHROMOSOME_I 2 1 27M1D73M * 0 0 CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #############################@B?8B?BA@@DDBCDDCBC@CDCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-18 XS:i:-18 XN:i:0 XM:i:5 XO:i:1 XG:i:1 YT:Z:UU MD:Z:4A0G5G5G5G3^A73 NM:i:6 +SRR065390.921023 16 CHROMOSOME_I 3 12 100M * 0 0 CTAAGCCTAAATCTAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############################################???88:;98768700000<>:BBA?BBAB?BBBBBBBB>B>BB::;?:00000 AS:i:-6 XS:i:-13 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:10G0C10G77 NM:i:3 +SRR065390.1871511 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA 0:BB@>B<=B@???@=8@B>BB@CA@DACDCBBCCCA@CCCCACCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3743423 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################?6@:7<=@3=@ABAAB>BDBBABADABDDDBDDBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4251890 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###########@BB=BCBBC?B>B;>B@@ADBBB@DBBBBDCCBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5238868 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA @,=@@D8D;?BBB>;?BBB==BB@D;>D>BBB>BBDDBA@@BCCB@=BACBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8289592 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############################A?@C9@@BC=AABDD@A@DC@CB=@BA?6@CCAAC@+CCCCCCCCCCCCCCC@CCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14497557 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ######@:@@.>=><;;B>AB>>BB?B=>B=BD>BDADDD>CCDDDBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15617929 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA D?;;D>?C>CBAAACD@BB?B>BBDB>@BBDDBDC@CBDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16049575 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #######################@??BB8BBB@@:AB@BDBCCDCBDCCCCACCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17838261 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################@>=?B@DCBDB>@D>DBADCDDD>CC@DCCCCBCCACCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22711273 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #############################B<@=<:6/0307==72@@=?788==;AAA:@CCAACCC?CCAACCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22922978 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##########################B=B>A@BBBC??=@=A@AC<><<8>C6CCCCC8CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23087186 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ############@:73???@6;D?B>:>BBA?B<>B@B>@B>@>BCDCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23506653 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############A/=A5::87@:=>6@AA>@CDBA@ABCB?BC>CD>DDBDC@CCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23791575 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCCCACCCCAACCCTTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##############################B4;:=B@>A@BCB@@ABCCBB@BCC@CCDCCDCCDCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:7T0A1G2T2G3A79 NM:i:6 +SRR065390.25911768 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##############@8B@B?9=:A?=@DDB>;B6?DDBCABABB@DDCCBDBDCCDACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26055380 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################################DAA><0=>=B;?BACDBDABCBBC@CACACACACCACCCCCCCCCCCCCCCCCCCCCCBCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26121674 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################?:AA::@DAAA>B??@A4@=BBBBDDBDBDCCBDDBCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30352568 16 CHROMOSOME_I 3 7 100M * 0 0 CTAGGGCTAACCCTCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################################################################A>>5A?CCC@CCCCCCCCCC?CC:C@A@==@A@A@ AS:i:-10 XS:i:-19 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3A1C4G3A37G47 NM:i:5 +SRR065390.31341126 16 CHROMOSOME_I 3 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ########################?AD?D@BCAABBBD@=DBCDBAACCDCAABCDCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.33653624 16 CHROMOSOME_I 3 17 100M * 0 0 CTAATCCTAGGCCTAAGCCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################################??8?000-+0000,@ABBBB@B:B@B>BB????>>>@@?::?6?>>;>>@ACCCCBCCBACCCC AS:i:-6 XS:i:-19 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:4G4A9T80 NM:i:3 +SRR065390.28043279 16 CHROMOSOME_I 4 0 9M1I90M * 0 0 TCTTCCGATCTCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #####A>=7A6DD=@AA?>AAABC@CAABDBCBBABDADBADCABBBDCDCDCACDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCC AS:i:-26 XS:i:-26 XN:i:0 XM:i:6 XO:i:1 XG:i:1 YT:Z:UU MD:Z:1A0A0G2T1A0G89 NM:i:7 +SRR065390.29270443 16 CHROMOSOME_I 6 1 100M * 0 0 AGCCTAAGCCGAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ###################################@:88@@>B>C>CCCCA@CCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:10T2G86 NM:i:2 +SRR065390.1364843 16 CHROMOSOME_I 11 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ####################@=A=8@:>@;@@=>>B8?C6CCCCCCCCCCACCCCBBCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10190875 16 CHROMOSOME_I 11 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ##################@@@@@@;>BBB?>A6BAB?BB=BAB@?:A.<===@7:4::>8D@BABBACCCCAB@CCCDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13556211 0 CHROMOSOME_I 11 0 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGATTGGAAGAGCGGCTAAGCAGGAACGCCGGGCTCGATCTCAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCBCDCCB>BBBBB########################################### AS:i:-50 XS:i:-50 XN:i:0 XM:i:25 XO:i:0 XG:i:0 YT:Z:UU MD:Z:57C0C1A0A0G0C0C0T0A0A1C6C0T0A1G1C0T0A0A1C2A0A0G0C2A3 NM:i:25 +SRR065390.20524775 16 CHROMOSOME_I 11 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ############################?9<8B=?@C8A<@?@C8CBDCCC=CCCCC??@CCDCCCCCCCCCCCCCCCCCCCCDCCCCCCCDCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20580336 16 CHROMOSOME_I 11 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ############################?:>@?@=>@=0<:CB>@B=DCADB@CCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22573273 16 CHROMOSOME_I 11 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ##################################A9;?@CBBDBA>BB;ABDB>AAA;=>=0943@########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20870114 0 CHROMOSOME_I 12 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCABCCCC=BBBCA@B>B?D;B=>9?############################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3863623 16 CHROMOSOME_I 12 1 100M * 0 0 CGCCTACGCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ##############################?@BB>B@BCABBB?DC@DADC@DCDCACDCBCCCCCCCCCCC@CCCCCCCCCCCCCCC1CCCCCCCCCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0A5A5A87 NM:i:3 +SRR065390.1659845 0 CHROMOSOME_I 13 0 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAACCTAAGCCTAAGCCCAACCCTAAGACCGAGACCGAGACC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCAB@CCC######################################### AS:i:-22 XS:i:-22 XN:i:0 XM:i:11 XO:i:0 XG:i:0 YT:Z:UU MD:Z:60G14T2G6C1T0A2C1T0A2C1T0 NM:i:11 +SRR065390.1567418 16 CHROMOSOME_I 15 1 100M * 0 0 CACAGCCTACGTCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #########################################?:8A@<@>>BBB8>BBB@BBBB>@:??::87688:?:::?@<@@97866@?>@@;;>:< AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T0A6A1C88 NM:i:4 +SRR065390.4996386 16 CHROMOSOME_I 15 17 100M * 0 0 CCAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###################################@@@@A=BB@C>>DCCACCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-22 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T5T92 NM:i:2 +SRR065390.14822977 16 CHROMOSOME_I 15 1 100M * 0 0 CGAAGCCAGAGCCTAGGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################################B:B?:==2>6@B@@C>?>A@CB5@??@28C@CCCBC@CC?CC?A@CC:CBCCCCCCCCCCCCCC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T5T0A6A84 NM:i:4 +SRR065390.15148736 16 CHROMOSOME_I 15 17 100M * 0 0 CTGAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###########################CCBC<=C;9??<;==C@BCCCCC=CCCCACACACCBBCCCCCCCCCCCCCCCCCBCCCCCCCCCCCBCA?CCC AS:i:-4 XS:i:-21 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2A4T92 NM:i:2 +SRR065390.18089757 16 CHROMOSOME_I 15 1 100M * 0 0 CTGAGCCTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ########################A212.0:?.>8?BB?B<@@C?CCBCB;DCCCACDCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2A5A91 NM:i:2 +SRR065390.25601994 16 CHROMOSOME_I 15 17 100M * 0 0 ATAAGCCTAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #####################???DD?BD?BDBB>ACBDBDDBDDDBDBDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-21 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0C9G89 NM:i:2 +SRR065390.29400981 16 CHROMOSOME_I 15 17 100M * 0 0 CGAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############################A<:?C>>BCABABC?AD>BDADDDBDBBDBDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-18 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T2G95 NM:i:2 +SRR065390.1056430 0 CHROMOSOME_I 17 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGC CCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCDCCDCCC:@<:<@=:>>DD6?################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:96A3 NM:i:1 +SRR065390.32986719 0 CHROMOSOME_I 17 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAGC CCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCC>C@@C@@A?8?@==0><:??@C?7:@B############################# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92G7 NM:i:1 +SRR065390.25620225 16 CHROMOSOME_I 17 1 100M * 0 0 AAGCCGAAGCCGAAGCCTAAGCCGAAGCGTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #########################################?1?<8@=CC@>CC?CCCCCACCCCC@@ACCCCCCBCCCCCAACCCCACCCCCCBACACC AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:5T5T11T4C1A69 NM:i:5 +SRR065390.1843941 0 CHROMOSOME_I 18 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCBDCDDBADDDDD@DADDAABABBB>BBA?>>B;>@8=@@:@83@>AAA:A6?<4= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1866654 0 CHROMOSOME_I 18 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCDCDDCDCCDDB6:?@B=;@@=@@:A=B@??A=@<41@##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2940592 0 CHROMOSOME_I 18 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCBC@@=CB?B=?A@@DD>DB=?>B7@8@@?BABABB@3>D9=?(@==A=A##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3916542 0 CHROMOSOME_I 18 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCBDDCDD@DDDDBABDDDAA?BC@<:?@B?A????@?<@@<@;D@?@9 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9532073 0 CHROMOSOME_I 18 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CACBCCCCCCCCCCCCBCCBCCCCCCCCCCC@C=CCCCCCC@CCCCCCC@C=?CCA=CCBACCAB?@BABCB=@B8BA=A::;8;BB>8>=??####### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22616746 0 CHROMOSOME_I 18 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCAC@CCCCCA@CCAA<::>BB?@88@@########################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26956496 0 CHROMOSOME_I 18 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CACCCCCCCCCCCCCCCCCACCCCC@CCCCCCACCC@DADBC@BACAAC@B<@@BAA@A>@>?B@################################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10808349 16 CHROMOSOME_I 18 0 18M1I81M * 0 0 TGCGCCAGCCCCAGCCCCGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCGGCCTAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #################################################################?A??ACCCCCCBBACCCCCCCCCCBC@CCCCCCCC AS:i:-33 XS:i:-33 XN:i:0 XM:i:11 XO:i:1 XG:i:1 YT:Z:UU MD:Z:0A2C0T0A4T0A4T0A41A0A6G31 NM:i:12 +SRR065390.10873351 16 CHROMOSOME_I 18 0 100M * 0 0 AGCCTAAGCCCAAGCCTAAGCCTAAGCCTAAGCCCAGTCCCGAGCCTCCTCCTAAACCTCACCCCAAATCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ######################################################################CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-30 XS:i:-30 XN:i:0 XM:i:15 XO:i:0 XG:i:0 YT:Z:UU MD:Z:10T23T1A0G2T0A5A0A0G5G3A1G2T2G0C31 NM:i:15 +SRR065390.15490530 16 CHROMOSOME_I 18 1 100M * 0 0 CGCCCCTCCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ###############A@A5ACAB?<0ACBB??CCBBA@?CCC?C@?CCAACCC@AACCACCCC;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0A3T0A0A0G4A87 NM:i:6 +SRR065390.1909715 16 CHROMOSOME_I 19 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ############@B@:;0=:1@B5ACD@DDCC@@@DACCCDDC@CCCCCCCCCCCCBCCCCCCCCC@C@CCCCCCCCCCCBCCCACCCCCDCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7382123 16 CHROMOSOME_I 19 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ###############??6D?B?D>?B>?B>>?@BB;@BBB@??>AB@B@DCADABBCDBD?CCCACC@CCCCCBACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20593989 16 CHROMOSOME_I 19 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ####################@=698@?8:4>=BDBDDCCDBAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25363430 16 CHROMOSOME_I 19 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ########A663>BB>CBABBAAAA?A??;BCDBAADCDDBCDACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32419676 16 CHROMOSOME_I 19 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ###############A1=@?A@6A?>BD6?AABBBBB@AD>BBDBD>CDCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22906057 0 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCAAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCA@CCC@ACB@C=CC;=BBBB>;AABA################################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:86T13 NM:i:1 +SRR065390.27521332 0 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTACACCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCATAAGCCTCAGCCTA BBBBBBBBBB**9+7BBBBBBBBBBBBBBBBBBBBBBB@BB@>BB;B@BAB;BB@BA>ABA>A4A################################### AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:10A0G73C7A6 NM:i:4 +SRR065390.30947354 0 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGACTC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDCC@ADABCBBBBBAABB>BA>B?@@B################################### AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:90C5C2A0 NM:i:3 +SRR065390.31587235 0 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC'AAA@CCCAC@DCDC@;BABB@>@B?A@4;;8@??>:DBD?>:A AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:45A54 NM:i:1 +SRR065390.1370038 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #####@B>;DAB?B@=@@B=@BBB>B@@BDDB>DDDACBBCDDCCBC?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4643729 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #########################BD6;@BB@BB?BDDBDDDCDBCDCCBBCBCCCCCDCCCCCCCCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6133344 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ####################@?BB@999.4A;;;:C8C@@@A@>B;=;==CCCCCC@CCCBCCBBC?CCCCBACCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6927609 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###########D?D@6@@@@3:>CCAABA>ABB>ABBB?>BB@@BDDBDCDA;BCCDCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7858967 0 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGTCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCC>CCCCCCCCCCCCDCCCCBC;CC:AB>A?<@'>ADBABB>CAABBB>>B@B;BBB;BA?7>989?D?@?########## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:48C51 NM:i:1 +SRR065390.8362231 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA 3AA3@AA==.>>>>=4@?@?;BBBAAA>@@AAB>DDAB@BDDBDBBBDCC@CCCDCB@CDACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9016128 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ################?B@?=<9=:@>=7?AA??=A=??:7B=;=A=C?CB8B>C?ACBCAAAAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11434451 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ########A9<=?B@B@?:CC=:?DAA>A@BBA>B@B8BD=DBBBC@?DD<ABBBDBBBDDB@B<>DDBBCDCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20362361 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #######A1:6DBB?C;BBD=B@BDBABADDBCB@CBCBBACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28067938 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###############@6=?@75595=7:=:;:A1@BA@@C@CACC6CAACC9CCCBC?@CCCCCCCCBBCCCCCCCCCCCBCCCCCCCCBCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28676889 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ######################D@D<>BBB86.5/B=7/7B<@@?ABA;BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31914072 16 CHROMOSOME_I 20 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #######################BCC>AADDADBABDCDDBCACCDCCCCCCAADBDCCCCACCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28534879 0 CHROMOSOME_I 21 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCATAAGCCTAAGTCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDCCCDDDBB89BAAA@@?DB:@@9>====?########################### AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:81A2C10C4 NM:i:3 +SRR065390.2215027 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDCCCCBC@BB@BCDDBDDBA@DDBBB8@BB>B?=B?>B?>CBAAA?9>>A>:6@= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2347049 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCBCCCDCCCDBDBADDD@AAD@BBDBBBCAA>@C??################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3130808 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCA@ACCCCC>AC@=CBCC@@BBBB=>BA.A=:?A@@@:>@####### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4139123 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCDDCBCCCCBACBBB;DADBD;?BDB>;BBAB=;DDBBB>??BB>ACACC?>.A@=>,@########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5087657 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCACCCC@CCCDCCCCC>B@CC@CB;@CBAB1B@=BBB@BA;A8??B:==B=@@?>><=6=6D@@>::9>9><=@@,@@@14;<@####### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10185722 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD@BCDBBBDBDB@<@BBBB>DB>B@=BDBC>A;@@DD<4=@=<@6@###################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14268858 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCBCADCDBCABDDBB>BBBCBBAD?CA?>>BCBB?AD?BA?=99>8;8@;@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14318056 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=ADACBBABCBBD>AD=25867BB@BBBBA@;<>A=AAAA?A8?<>B78*=8=<>@###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16702871 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCDACCCCD@BCCCD?DDDCD?ABDDB;BBBB>?@?A@88B:@=2/99>A3.A##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18871990 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDCBCCBDBDCDDDDBC?;;B@BB>?D:>BBB@94@########################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23185275 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCC?DD@A@B@?BB>BB?>BD?########################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26311247 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8CCDCDADB@;BB?@>:D>BB=>:DD>@=@>@?6?AA?AA############ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31584477 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCDCBCCCDDDCDCDDDDCDDDDCDDB?DABBBCBBABBCCBA?AAA=?D?DAA:AAACA>AAAA?################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.33157605 0 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBC8?>??DBBBBA@?CBA=?=>BB@?@=<=?B@BAA@@:=>::8AAA>BBBB3:===8D?B<:DD<:?#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5496550 16 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ##########@727;=>/7=<=B:=@@ACA?A8CB@B;A@CCB?BCCC@CCCCBCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17740346 16 CHROMOSOME_I 23 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ###############A;:>A7>=9=:.>==@A=BCCCBACCCCDBBB>B@BBB;A??BB;DAABD@DACCCBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16643153 0 CHROMOSOME_I 24 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTAAGCCTAAGCCTAAGGCTAAGGCTAAGGCTAAGCCTATGCTTAAGACTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC################################################################### AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:45C16C5C5C9A2C4C7 NM:i:7 +SRR065390.1203526 16 CHROMOSOME_I 24 1 100M * 0 0 ACCCTAAAACAAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ###############################A==B7277*@A?5AB9A@CCCDCDABA?:?A@ACCCCC?CC?CCCCCDCCCCCCCCCCCCCCCCCCCCA AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1G5G0C1T89 NM:i:4 +SRR065390.1571837 0 CHROMOSOME_I 26 0 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGGAAGCCTAGGCCAGAGGCAAAGCCGAGGCCTAAGCCGA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCC>40?######################################### AS:i:-20 XS:i:-20 XN:i:0 XM:i:10 XO:i:0 XG:i:0 YT:Z:UU MD:Z:61C0T7A3T0A2C1T5T1A9T1 NM:i:10 +SRR065390.26106665 0 CHROMOSOME_I 26 0 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCAAAGCCTAAGCATGAACCTAAGGCTCAACCTAAGCCGCAGCCTAATGCTAGGCATA CCCCCCBCCCCCCCCCCBCCCCCCCCCCCACCCCCA0AA############################################################# AS:i:-29 XS:i:-29 XN:i:0 XM:i:14 XO:i:0 XG:i:0 YT:Z:UU MD:Z:36C7T10C1A1G6C2A1G8T0A7G0C3A2C2 NM:i:14 +SRR065390.28275609 0 CHROMOSOME_I 26 0 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAACCTTCGACTAATCCTACACGCACGCATAAGCCTCCCCATA CCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCDDCDCBBDCBDBABB6@C################################################## AS:i:-30 XS:i:-30 XN:i:0 XM:i:15 XO:i:0 XG:i:0 YT:Z:UU MD:Z:59G3A0A1C4G4A0G1C0T1A2C7A0A0G1C2 NM:i:15 +SRR065390.7812 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##############################@::?>=CB@CACCC???CCCBAB@BB;?B@B==@ACAA@?C?BBCBBCBCCCC@@CCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2770334 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################A<8.@@@=A?@?B?@>CBB=B8BAC;@BBCAAADCCCACD@CCC@ACC?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5038515 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #####################@>BB>B;@@BBBBBDD@D@BCCADA?CCBCCCCCDC@CCCCCCCCCACCCCCCCCCCCCCCCCCCBCCBCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5869665 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ########################@6A@?@A;B=BCC8BC@CC@BB@CC?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8368880 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA <:3:B??@4??DB><7;;84A>>DD?BADDD@DABACDBBCACCDDCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11712874 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA >8=?=:;;1;1??:2279772,5552-278A8?A1@CCB@:ACCC=ACACA9?=BCCCACCCCCCCB@CCCCC@CCCC?CCCCCBCCCC=CBCCBBCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12176045 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #####################B4BB@;B?B@@==0BC5B?ABDB@BBDCBCB=BCDCC=CCCCCCCCCCCCBCCCCCCCBCCBBCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12322670 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####?@@=6<??:>BBBBAAABBBB=DBB@4ADBBDABCCBB>CCCBC=@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14671547 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############?A@A8@@?@BBD9BB@@?CCCDDDA>CCAD?CCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15954948 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###A97==00;A????;=BCCBD>DCCCCCCCCCCC@CBCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17314912 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #############################AA54=?A?<8?@4:8)??:==.A>7;=3CCBCC@CCACC;CCCCC;CCACCCCCCCC@CCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17920847 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################@(=@@9632;283*38762-8AAA=8@CCCBACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18484794 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################@A=B@4BC?AA>CCBC@ACCBCAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19979752 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ??@?AA>8=<;>=:2>;>BBA6ABB?>BABDB>BBBBB@>BDDBDDAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20318652 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ############?A<8BBB8?A=B<8AB=CACCCCC@CC=CCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20730275 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##############################?4?::BAAAAACCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24048983 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA 98(934>>39/<==9>3>>A.BDB?C;CCBD>BBBBDDABBDBBBBDBCCDCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26914314 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############@;<:AAA?>?>>BBB>:ABBBBDADBBBBDDDD@DDCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29129737 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ############A?7;B?B>A6AA?:>:@@B;AABBA?@5DDDBADCDDADCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30130221 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #########################ABBABA@@;@@@@@BB;B>B@CCC?CCACCCCCCCCCCCCCCCCC@CCCCCCBCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30619064 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ######################@@?>@3>DA6?>AA@?@>BDDBD@DCCCCACCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31338027 16 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###################################@>=>@BBBAABBBDB>BB@B=DBABCCCDCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31592423 0 CHROMOSOME_I 27 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTGAGCCTCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCACCBCAACCDDD@BBCDBD############################### AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:74A17A5A1 NM:i:3 +SRR065390.7084193 0 CHROMOSOME_I 28 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCBCCD@ABDCB@=>BBB>>>BBB############################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:96T2G0 NM:i:2 +SRR065390.19170893 0 CHROMOSOME_I 28 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTACGCCTATGCCTCACCCCAAG CCCCCCCCCCCCCCCCCCCCCCCCCBB######################################################################### AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:68A11A5A4A1G2T3 NM:i:6 +SRR065390.22308979 0 CHROMOSOME_I 28 0 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAAGCTACGCTGACGACAACGCCACAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCDDDCCCBACCCA########################################### AS:i:-24 XS:i:-24 XN:i:0 XM:i:12 XO:i:0 XG:i:0 YT:Z:UU MD:Z:64C10G0C3A2C0T1A1C1T1A3T0A2 NM:i:12 +SRR065390.5010743 0 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGC CCB@@CCCC@CC@CC@CCC?C5CCC<<8:?=@@:;CCC@;=CC8;@CCCC;1?C@:858?5618/?=695;9@@;>?B###################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:97A2 NM:i:1 +SRR065390.5559541 0 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACACCBBCCCDDBACB@DD@B>@BB=BD?;B@=??85797;@::@########### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:97A2 NM:i:1 +SRR065390.31135792 0 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCBD@CACDDBDDBBCBBDBC>?BAABAC?BBAAABCAAAAAD:D<=<3<9<@####################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93C6 NM:i:1 +SRR065390.1936876 16 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #@>?B5555(=<:=?@@A?@;>>B?D?BDBBDDDDBBBC@BC@CCDCCCCCDCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16850763 16 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #######@8?73=/=@=:=7@A==A;;@;9C@@@BDA@CCADCCDCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17680911 0 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACC CCCBCCCCCCCCCCCCCCCCC@CCACCCCCCCCCBBCBCCDCC=?CCABBAAAB@4BC?@:?@@B*B1B>B####################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98G1 NM:i:1 +SRR065390.24171347 16 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #####################BB@DAD@B?A>BADBBABADABBB;DBBCDBCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24428216 0 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACC CCCCBCCCCBCCCCCCCCCCCCCCCCCCCCCBCCCCCC@CCACC8??>A@?@@(=8==@=@8A@A>A##################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98G1 NM:i:1 +SRR065390.27070077 16 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ##########################?A=?@?@6@AAAAA>@CACB;BBABBB@BB>@DDCCDCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.27769553 0 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBCCCCBBABDABABDDDD?DBBABACBBBBC>>B;D1?B??D?:B?2@@=:=A?=?A=@######## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93C6 NM:i:1 +SRR065390.32563299 16 CHROMOSOME_I 29 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ###########@;;@.<@@?A?B@B?AAAABDCBBBDAADABCDDBCDCCDDCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2792992 0 CHROMOSOME_I 30 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGTC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCBCC@CCBCDBCCBCBBBDD@DBADA@BB>BB=>:AABB>@B@>B?:D?D################# AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:95A2C1 NM:i:2 +SRR065390.639284 0 CHROMOSOME_I 31 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCDCCCAADA>C=@A@@@><@B@B=B4>@############## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1105550 0 CHROMOSOME_I 31 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCBCC;A?CCACACCDB>? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8156389 0 CHROMOSOME_I 31 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCC>CCCCACCCBCC@@CCCC@CCCC@@CCCC=@@ADD?@@BBBACBA=DAA< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11912243 0 CHROMOSOME_I 31 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCCAAGCCTAAGCCTAAGCCC CCC@BCC@CB>CACCCCC@CC??C@CCCCBCC?BBCBC@+=A5=1==:=76+@#################### AS:i:-7 XS:i:-7 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:78G2T17T0 NM:i:3 +SRR065390.17298969 0 CHROMOSOME_I 31 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCAA>BBACA>AA>>C:A?A>?<<< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20623938 0 CHROMOSOME_I 31 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCCAAGCTCAAACGC CCCCCCCBCCCCBCCCCCCBCCCCCCCC?A@CCCCCCACCBC@C:::?:@8?######################################## AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:76A10T4C0T2G1C0T0 NM:i:7 +SRR065390.21172388 0 CHROMOSOME_I 31 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTACGGCAGAGCGG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCC>>CCCB48@BBAA.=@@@0.=>:=*7??####################### AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:85C3A1C1T0A3C0T0 NM:i:7 +SRR065390.32636364 0 CHROMOSOME_I 31 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCACCA@?CCC@BACBABA@B@@?B@DB8:=4=9;2B########################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14726933 0 CHROMOSOME_I 33 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCCCADCCAABD@CBBBB=BB8BBBB>;DB;B@@B>B########## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92A7 NM:i:1 +SRR065390.19804249 0 CHROMOSOME_I 33 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTAA 00.00?????CCCCCCCCCCCCCCCCCCCCCCCCBCCCBCBBBBBBBB@@B>@>@@BBB=<>>>>=>?0?############################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:87A12 NM:i:1 +SRR065390.641561 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCC?BCCCCC@AA=C@C?BBC8@=C@@A@A@;=?@>A95<=>=*=9:<@################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4398044 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCDCACDDB@DB@@BA>B@@A><@@?@)?B72=77B############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9917822 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBACCDD@BDBDBDBB@B?@@<@@?:D???<@??@==@3@@1<@=<<9< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13766985 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCACCCCCCCCCCC@CBDDCBCDABBB=<@BBABB@BBB=B4BB>BB?4???>B>8DB<.?? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13985245 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCADCDACCBDDA<@BBBBB@BBBC=>B>BCB>AA>AA>D==; AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15076148 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCBADDCBCABC=CCB@@;B@@?B8?@@;?8<:A:==?BAD?;@B@=@.@D@??2=? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16049660 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=CCCCCCCCCBBCCCCBD@ADBB@@?@BB?;?B>20+7/<===@?######### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22701424 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCDCCBD?@@@ABBBABA?ABAB=3A;B?;D?DD>B5@69<6:=5=> AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32125404 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACDCB;@@BB<;@@@A@:?A?@?6AAAA############################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7546701 16 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #####@?.:@?BAA>DBBD<=BAB>BB>BB>DB>BC@DCDCCBCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10989112 16 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG 5050388648?AA6A===)77;==5:>BBCABBDDCBBADCCC?C=CCC@CCCCCCC@CCC@CCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11531996 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCBCCDCBBCCDABB@@BABBBB?B?ADABDB:@7.?=4A=:9A=???D>=(;4 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16826146 16 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG 9=59>@??;B==<::1@@@>8BB>BD=@CCCA@ACDCB@CCCAC?ACCCCAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17948445 16 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #####@4@4@8A>::<>5>=68AABC>CBABBCBC?===:B?DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29829737 16 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ############################@B?@>BB@4=AA@@?A@?BC<@DBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29888392 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCDCCCCBCCCDCBDDBDCBDABBBADBBABAACA@>?@>?B?>BD=>@==A3<<.773783A################# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30225547 0 CHROMOSOME_I 34 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCADBBDAADBABB>ABBABA>BDBB<>>?8<>55>'0626526@88A0;3'5 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8226077 0 CHROMOSOME_I 38 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCC@CBCC@CCCDCCBCCCACBCCDB;@=C?BC########################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80T19 NM:i:1 +SRR065390.17492028 0 CHROMOSOME_I 38 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACACCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCDCCDCA@@BACB==BBBA;4BBBBB@B??#################################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:94A0G4 NM:i:2 +SRR065390.17605413 0 CHROMOSOME_I 38 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCA?CCCCCCDCDACA@<=8@==*51553BB?BB?;@*?##### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:96C3 NM:i:1 +SRR065390.20811266 0 CHROMOSOME_I 38 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB@BCC@ACC8;;:;CCCCC=A@5CBCB5=?7<<>>A:.@######################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:88A11 NM:i:1 +SRR065390.25876953 0 CHROMOSOME_I 38 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAATCCTA #################################################################################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:95G4 NM:i:1 +SRR065390.27381447 0 CHROMOSOME_I 38 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGTCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCDDCCCCACDCCC@-A>A>>DAB>@A?AA:A>AACAC6<@@###### AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:54C45 NM:i:1 +SRR065390.32350443 0 CHROMOSOME_I 38 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTACGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCDCDDCCDBADCDDACBDB@=DBBDAB6C@######################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:84C3A11 NM:i:2 +SRR065390.26113957 16 CHROMOSOME_I 38 1 100M * 0 0 CCTCCCCCTAAGCCTGAGCCTAAGCCTAAGCCTAAGCCTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #########################################A=B7===;:?@??:B?CC?CAACCCBACCBC?CCCCCCCCCCCCCCDCCCCCCCCCCCC AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3A0A0G9A23A60 NM:i:5 +SRR065390.22114448 16 CHROMOSOME_I 39 1 67M1I32M * 0 0 CTAAGCCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ############################A:B;@@>?B@?ABBDABB@BC?BAACC>BCCAC>@CCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-10 XS:i:-10 XN:i:0 XM:i:1 XO:i:1 XG:i:1 YT:Z:UU MD:Z:7T91 NM:i:2 +SRR065390.4122396 0 CHROMOSOME_I 40 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACG CCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCBCCCDCCCCC@DDCCCA>DDDBBBABB<@C>@BB?8@@@;87?9<700727;7/7<@@@###### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.12501634 0 CHROMOSOME_I 40 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCCAAG CCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCDBCDCCDCB@DB>@BBDDABD@BB><@=@?############################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:84T11T3 NM:i:2 +SRR065390.15005277 0 CHROMOSOME_I 40 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDACC?CAACAA@A:ABB=;1@################################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:86A13 NM:i:1 +SRR065390.22489915 0 CHROMOSOME_I 40 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAG CCCCCCCCCCCCCCCCCCCCC?CCCCCCCCCCCDCCCCCCCBDCD@C@BACB@@B@BBBB@:@==B:B<@BB3>?######################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:94C5 NM:i:1 +SRR065390.25381446 0 CHROMOSOME_I 40 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCDCC@@BBCCADDDB################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:66T33 NM:i:1 +SRR065390.26177760 0 CHROMOSOME_I 40 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCAAAGCCTAAGCCTAAG CCA@CCCCB@CCCCCC@ACCC?CCA9<:<=9;??6?########################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:79A4T15 NM:i:2 +SRR065390.26407476 0 CHROMOSOME_I 40 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGNCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGTCTCAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCC/C00!+03;999CCCCBBCCCBCCBCCB?BBB@BCBBBABBB######################################## AS:i:-5 XS:i:-5 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:22C59C2A14 NM:i:3 +SRR065390.13931899 16 CHROMOSOME_I 40 0 100M * 0 0 TAAGCCTAACCCTATCGGTATCCCTACTCCTGCGCCTCCGCCTTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###################################################CCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-28 XS:i:-28 XN:i:0 XM:i:14 XO:i:0 XG:i:0 YT:Z:UU MD:Z:9G4A0G0C0C2A0G4A0G3A0A4A0A4A56 NM:i:14 +SRR065390.1371033 0 CHROMOSOME_I 43 0 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAGGCCAACGCATAAACCCCAAGCA :@@B??4?????3??77938<=<7?>39??B8A?A@@C???A>>BBBACCBCCCCCACBCCBBCCCC@?@??BB>B> AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0G5G1C8A5A76 NM:i:5 +SRR065390.3034972 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT >B>B;@B=B?><@B@B>>@>BBDBBADDBBA>CC?@CCCBCACCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5390013 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #####################@88C8:?=AA1:A;8C5=CCAC=@ACAC=ABBDBBB@DDDBB@CD@DD@CCCCDCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10370271 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #########################################?>BB37:7/:8:/75;7;77;=?4><;CB@A;@CCCCC@C@CCCCC@CC?CCCCCC@CC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11422655 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ######ABAC>?DBBBDBBBDADD@>DCBBDBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15298468 16 CHROMOSOME_I 43 1 100M * 0 0 GCCCACGCCTAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #####################################AAACC=ACC1ACCACC2BCC?C@ABCC?AA?A=C>CCACCC@BCCCCCCCCCCCCCCCCBCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3T1A6G87 NM:i:3 +SRR065390.20235987 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #############@@9:7:8BAA>ABB?@BB:B?@AA=DDA@ABBADDCCCBCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21015579 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##########################A;@=B@;BBA@CA=CAC@CCCCDCCCCCACCCCC@CCCCBCCCCCCCBCCCCCCCCCCCCCCCBCCCCCBCBCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21101533 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##########################??A;=ABBAA>BB>ABADDB8DADCBCCCCCCCCDCCCDCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23753867 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ######################??6?B@:DD6D>AA?>C;BBBC>BBDD@BBBBCBDCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26254463 16 CHROMOSOME_I 43 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ######################@@@>=:>8?BB>B@=@A@=====@B;B@BBA;7B=AA?8BBB##### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:96C3 NM:i:1 +SRR065390.31555089 0 CHROMOSOME_I 44 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCBCCCCCCBCCCCACCCCBBBBB(?A??AA=B=CCCCDC>AC=BB@?B8>==:BB@6?#################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:45A54 NM:i:1 +SRR065390.4469707 16 CHROMOSOME_I 44 1 100M * 0 0 GCGAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###########################@>==@A>=.@@@?CCCCCC@=CCBC@CCCBCC>C@C==?=>?ACC;;>5>@=CA?9A############################################# AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:68A12A5A6G1C0T0A1 NM:i:7 +SRR065390.28536327 16 CHROMOSOME_I 45 1 100M * 0 0 CGTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ######################A:A@(6@@>:9:>553+(>@7<>=B:A@5BCDCADCBAC@CCCACCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCC AS:i:-7 XS:i:-7 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T0A35A61 NM:i:3 +SRR065390.30452237 16 CHROMOSOME_I 45 1 100M * 0 0 CCAAGCCTAAGCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #########################################B@=@A=@DBCDCDCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T13A84 NM:i:2 +SRR065390.473101 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAGCCTAAGCACCAG CCC@@C@CCCCCC@CBC@C@C:?@@==;@=CBABC@CAC9?2?;2A6AA@################################################## AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:76C18C0T0A2 NM:i:4 +SRR065390.2292661 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCDCCCCCACCCBCDCABCB@CCDBABC@######################################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4943586 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCABCCCC=BCC@@@BC@B<@BAB?<;5@?877;7;>D>?D:>?=>@@@B=6@@@###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5569754 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACBCDCCBDCBB@CBBBBBDB;DB>@ABBA?CAAAAAAA@AAAA########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8043944 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB@DCCCBCCBCDDADDDD>DBBD@B@@ADB?>B>B@B@>CBBABAA?BDB4@>??DAAA7A AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12047482 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCA@C@@BAB@DDB>B@;@A:@@>DC=;@@DBBBBBBAC>B?6B;?<8?:? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16134128 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACGCTAAGCCTAAGCCTAAGCATAAGCGTAAG AAA=ABBABBCCCCC>ACACBCCCCCCCB?CCC@C@BBB>3?8A>>@CC@@D@?###################################### AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:69G0C18C5C4 NM:i:4 +SRR065390.17957775 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCDDCBADBBCADDB<=DBABBBBB?C?DD>B::8AAA@@################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22147900 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCCAAGCCGAAGGCTAGG CCCCCCCCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCCCBAD=@=A=@5==:74@################################ AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:81G2T5T3C3A1 NM:i:5 +SRR065390.22676708 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACCCCGCCCAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCADDBDB@@DABABBDAD@?>6@@@@@################################### AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:88C1T0A0A3T3 NM:i:5 +SRR065390.22905722 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCDCDC@BBBBDBBBADB@BCBBB>A?>===92>9=985@###################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23066210 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDC?DCAB?>BCAB@DBDAA>>?BB??>DBB######################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24301313 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCDBDDADBBDDBBBCDBDBBBB>BAC>A>AAA53=@9>999AAA################# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25506513 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTCAGACTAAGAAAAAGACTAAG CCCCCCCCCCCCCCCCCCCCCACCCCCDBDCCCDDDDDCBBDBBDAA>BA################################################## AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:76C2A2C5C0C0T3C5 NM:i:7 +SRR065390.32874751 0 CHROMOSOME_I 46 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD6CB?>?;>ABAA6A??>(9<9:18868@68@:692:85 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12211289 16 CHROMOSOME_I 47 1 100M * 0 0 ACGCCTAAGCCTAAGCGTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ###################################@;6;BBB?B>A?DD@:999<<><<;87;89<<>>?<9??;::9;7883800000 AS:i:-44 XS:i:-44 XN:i:0 XM:i:18 XO:i:1 XG:i:1 YT:Z:UU MD:Z:0A2C1T2G3A1G0C4G2T2G2T2G2T0A1G2T2G5G48 NM:i:19 +SRR065390.26846416 16 CHROMOSOME_I 48 1 100M * 0 0 GCCCGACGCCTACGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ############################################################?BABC@CCB@AACCBCCCCCCCCCCC@CCCCCCCCCCCCC AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0A0G2T1A5A3T83 NM:i:6 +SRR065390.4887361 16 CHROMOSOME_I 49 0 100M * 0 0 GCCTTCGCCCTGGCCCCCGCCTCCGCCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##############################?AB>>BBDBBBBBBB>DBDCCDCBAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-24 XS:i:-24 XN:i:0 XM:i:12 XO:i:0 XG:i:0 YT:Z:UU MD:Z:4A0A3T0A0A3T0A0A4A0A3T0A71 NM:i:12 +SRR065390.27800038 16 CHROMOSOME_I 49 1 100M * 0 0 GCCTAAGCCTAATGCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ############################################################@A@@@B>>@>>AA6:@A>>CB@BBACBBB4?>??@@BA;B>B0@############### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93A6 NM:i:1 +SRR065390.4627990 0 CHROMOSOME_I 51 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDC?BDCABB>BA=B?@?B;?=BA@47??:?############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16715324 0 CHROMOSOME_I 51 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCBAADB=AB;@D0;BACB;BBBA;0>==5=3?@>@7477:@######### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18309630 0 CHROMOSOME_I 51 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA=CCCBBBCC?BA@B;BAB<:703=:=:::??@@@######################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93A6 NM:i:1 +SRR065390.19555357 0 CHROMOSOME_I 51 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAC CCCCCCCCCCCCCCCCCCCCCCBCCCCCBCCDCCACC@CC@CCDCA@@BBDDBA@BADC<@DBB;;@@??A>A@C######################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:99A0 NM:i:1 +SRR065390.20581090 0 CHROMOSOME_I 51 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCCTAA CCCCCCCCCCCCCCCCCCBCCCCCC=A?:A<;?;;A?;A=9=;9A####################################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:91T8 NM:i:1 +SRR065390.23080061 0 CHROMOSOME_I 51 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACAAC@CCCDBBDACDDADB@ABDB>ABBABA@CC>:A8B<<:?@>A@AAA???B### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26337922 0 CHROMOSOME_I 51 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAA CCCCCBCCCCCCBCCCC?BCCCCCCCCCCCCCDCADCCCAA2=:(@############################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92A7 NM:i:1 +SRR065390.10947804 0 CHROMOSOME_I 52 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGGCTAAGACTAAGGCTAAGGCTCAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CACC@@CBBC>=CB?A?5A######################################## AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:76C5C5C5C2A2 NM:i:5 +SRR065390.13041859 0 CHROMOSOME_I 52 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCTACGCCACACCCCAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCDCCDCCDBAABC@B@?BB?BBDADABAB8B?>>:9A########################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:90T9 NM:i:1 +SRR065390.20639196 0 CHROMOSOME_I 52 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAGGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@BCA=AA?CDCCCDACDCBBDDBBBBBBBBABB>?;>BBB?AADDB@D@BB@=BBA>=@BAB?5ACDDC5BACCAADCCC@ACCACCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1360842 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #############AA;9457A5:7@C>B:C@CCB@@CCCC5@=CC=7;===@?==CC0>9A=;;BB;BBB?>AA@9?CAC>@BBCCCCC@CCCCABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8944828 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ######D@D>>BDABAA@@ABBBBBDBD@@DDBBDADCDCBBCCDBDACCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9154510 16 CHROMOSOME_I 56 0 100M * 0 0 TTCATATGGGCAGGGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ##############################@B;@?>>B1?BCBBC@>CDB>B@CA@CCAC=AA>>AC;CCACCCCCCC=CCCCCCCCCCCCBCCCCCCCC AS:i:-28 XS:i:-28 XN:i:0 XM:i:14 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0C0C0T1A0G0C0C0T0A0A0G0C0C0T85 NM:i:14 +SRR065390.10327745 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #####?BB?>793=2=@7>75;BBDABDBBCB@CC@CCC89876@CCCC@B8@@ AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3A4T2G5G2T79 NM:i:5 +SRR065390.11441245 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #######################?=:>==8;;;231@==;B8BBA;?8AA9B@=CDABCDCD@CCCCCCCCCCCCCCCCCCCCCCCCCCCABCCCCCCBC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12629337 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ;=5?:8A?<:?8A@@A?==@6B=BDBBBA@CABC@DCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13640483 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA =>8=>3A@=6B=B@8B?>BDB@ABDA>BDBCCDDCCACCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18076115 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###########@<88>>8?<=;8A@>:=;*AAB=@C>@84=>5:535BCBB@DCC?A?DCC?CA9CABC@;CCBAABCCDCCACCDCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22432674 16 CHROMOSOME_I 56 1 100M * 0 0 CCCACGCCCAACCCCAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #####################################A?5@@AA:9B;BCCCACBCCCCCCCBCBCCCCCCCCCCCCDBCCCCCCCCCCCCCCCCCCCCC AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T1A3T2G2T8G76 NM:i:6 +SRR065390.24633504 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###############?>B==B:BC4BDAACDC@CCACCCCCACCDCCCCCCCCCCCCCCACCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30385823 16 CHROMOSOME_I 56 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ########################################?@?@AB@BBCD@B>CCBCD@BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.159947 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA <>4=96:98:?46?A6?B@BA=?>BBB>>BADBBBDA@BCBCCCCADCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1796988 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##############################################AAA:00000?=@BCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2760975 16 CHROMOSOME_I 57 1 100M * 0 0 AGAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############AABB@ABBACBCBC?CDCBCACCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCDCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0C0T2G95 NM:i:3 +SRR065390.12418490 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #############A8@AACBBB;;B@BBBB@CB@B@DADADA>CCDCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14521060 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##############################B?>BB@A=:<07;;7B@@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14712716 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #########################@@98@B<=@@B=?ABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17723586 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################################@:B><;75<@-==;CC@BCBC?CACBCCCCCCC>>==AA AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17845832 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################?@9A?88ABB0?@ABBBABA=B*BC=BC?CDCCC=DCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18910535 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #######################BABCAAB>BBBBDB=DBBD@BD@DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19689790 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################@33B@>B>ADA>B@@CADDCACCBACCCCCCCCCCCACCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19927220 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ######################CBBA>BBDDB>DBBD@ABBDCBDBDCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19989398 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA @@6@?@@:<@BBB@D>@D??>A?>CCBCBBBBAB@>BBAADBBBABDDCDDDCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28429399 16 CHROMOSOME_I 57 1 100M * 0 0 CAGAGCCTAAGCCTAAGCCTAATGCTAAGCCAAAGCATAGTCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############################################A:=@@.AC@CBCDCCCCCCCC;CBCCCCCCCCCCCCCCCCCCCCCCCCCC@CC AS:i:-16 XS:i:-16 XN:i:0 XM:i:8 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T0A19G0C7T4C2A0G59 NM:i:8 +SRR065390.29699086 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################################?:@?;:>=4B@BA?AB@BCB:BAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30602381 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###########################ABBB@>>B@B?;B?BB?@B;CBBB=BDCBCCCCCCCCDCCCCCCCC?CCCCC@CCCCCCCCCCCCCCCCCBCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30661211 16 CHROMOSOME_I 57 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ######??8?5<08<::=48?B6@B8;8=?=ABB=B;AABA@>BB;BBABB6BD>BDDDDDDCBACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1865058 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCDCCCBCCCCCCCBCCCCCCCCCACCCCCCCBCA?BBCCAA########################################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3486883 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG 000000000,00000AAAAAA>A=ABBA<:;8;592;77230/79111-9?+79?############################################# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5071220 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCATAAGCCTAAGCCTAAGCATACG BCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCC?6>=>=@9B=?==9==BA;;@######################################## AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:72T4C17C2A1 NM:i:4 +SRR065390.7153981 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCACCCCCCBCCCDCCCCACCCCCCCD@BDDDB:BA8>6>=)=>:==>>>5B?@@@96<:;@>0>> AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9722947 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDCDDDCA@DBDDAC?BBBBB?ABBB@;A>:=:?9?6A??########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13953914 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTCAG @@A?=CC@CC===A=CC:@@ACCCCCC@C<:8<839>=>?5=@@######################################################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:95C1A2 NM:i:2 +SRR065390.15007214 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCB;DDDCDBD@DACB>?=BBBBA=0>>DBBDD=ABDB@B@@@BABABCB>>AB?BBB4?6(? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16824019 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTCAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@DCCD@@ABBAA>>DADBBBBAB?BAA=A############################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92A4A2 NM:i:2 +SRR065390.16851488 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCCAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCC=8=A<=>=8:252;/@@A=?############################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:78T11T9 NM:i:2 +SRR065390.17897057 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAACCCCACDC@@>>BCBB8AAB>@############ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19083188 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCC@CCCCCABADCBAD@ABB0B@B@(@################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19427372 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCDCDDCABACD>BDDB?>BBBDA;D>A<>>DBB?A>DBBBA>ACB??><@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19483941 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCBCCCCCCCCCCC@CCCC@CC@BC=>4B?CBB AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23214436 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCABCCCC@CCCCCDCBDCAACBBCCB@CB@BBBB?;@@=BA>AABAA>;>AA.A@@?B?############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24888065 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTACG CCCCCCCCCCCCCCCCCCCCCCCCCCCDCBCDD@DBDAAADBBBBA###################################################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92A5A1 NM:i:2 +SRR065390.29491496 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCDCCBCCCCCCCCCC@ACCCCACCCCCCCCCCCBCCCCCDDABCDDBBBDBAABDB@A>;@B@AAA??0:+=544925??######## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31477096 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACACCTAAG CCCACCCBCACCBCCCCCCCCAC@@CCCC@@@>?@>B@@;>A>>>*865><9?;;@>=>@BB@B>B;>;;===B=>;AA?*-373BB(?B########## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92A0G6 NM:i:2 +SRR065390.23852108 16 CHROMOSOME_I 58 0 15M1I84M * 0 0 TTAGCATAAGAATAAAGTTTAAAATTTAGCTTAAGACAAAGCCTAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ########################################################?A@<=CCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-36 XS:i:-36 XN:i:0 XM:i:14 XO:i:1 XG:i:1 YT:Z:UU MD:Z:1A3C4C0C4C0C3G0C0C1A3C4C1T8G53 NM:i:15 +SRR065390.23932205 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCDDCCDCDADDDBDBABABDBBBBAABBAAB?CC=AAACA?8=@@68: AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24149813 0 CHROMOSOME_I 58 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCDCC@DDACA@=D@A=@BABBB6BBAAB=@B@AB71<>9>0:>1@6@## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1087596 0 CHROMOSOME_I 59 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAGC CCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCDCCBBCDCAA@CB@=9:::A################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92G7 NM:i:1 +SRR065390.26571979 0 CHROMOSOME_I 59 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAGCCTAAGCCTAAGC =???=>AA>ACBCBCCCCCCCC>@@############################################# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:75C24 NM:i:1 +SRR065390.31153791 0 CHROMOSOME_I 59 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCCCCCBABDADBADDDBBBBBBBB>@B?CA:AA>AC6=<:A:2:@###################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:85A14 NM:i:1 +SRR065390.33128805 0 CHROMOSOME_I 60 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTAAGCCTAAGACTAAGCCTAAGCCAAAGCA CABCCCCCCCCCCCCCCCCCCCCCCACCCCCDCDCCABBBAAA@?BA@<=0@@@<>B>BBBA>AB@################################## AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:69C10C13T4C0 NM:i:4 +SRR065390.8926768 0 CHROMOSOME_I 61 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCD@CDA?=>C88A==@.8:@=<4><@@86;@::@# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9390775 0 CHROMOSOME_I 61 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCB@CD>CBAADCC=AABB@@???@A######################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:81T18 NM:i:1 +SRR065390.12883674 0 CHROMOSOME_I 61 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCACACCCC=ACCCCABD@B@BADABBB:@@=@= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19474303 0 CHROMOSOME_I 61 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@DCCCC=CDBC=CACDC:>BBDB>?DB###################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32664926 0 CHROMOSOME_I 61 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCAAACC?BCBC;CCCBB>=@C>4@############################# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:82A17 NM:i:1 +SRR065390.33180966 0 CHROMOSOME_I 61 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACT CCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCACCCBCBCCACCACCCC@8?>AA############################################# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:97C2 NM:i:1 +SRR065390.14178092 16 CHROMOSOME_I 62 1 100M * 0 0 CCGAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ##############################DBBBD@AC@@A??C@9><;:CABDCCBCCCCCACCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T5T91 NM:i:2 +SRR065390.33093699 0 CHROMOSOME_I 63 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCC1'0000>=39A############################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:72C27 NM:i:1 +SRR065390.3811166 16 CHROMOSOME_I 63 1 100M * 0 0 CGAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #########################??>AB@?B?>@A==:BB@=??CBB>D@BDABBCDBDCDCDCCCACACCACCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T12A85 NM:i:2 +SRR065390.9360891 16 CHROMOSOME_I 63 0 100M * 0 0 GTGCGCCTACCGCTACCCGTCACGGCAAGCCTGCGCCTCCGCCTAACCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #####################################################@C@BBCCCCCCCCC1BCCCCCCCCBCCCBCCCCCCCCCCCCCACCCC AS:i:-40 XS:i:-40 XN:i:0 XM:i:20 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0C1A0A5A0G0C3A0G1C1A1G0C0C0T6A0A4A0A6G4A48 NM:i:20 +SRR065390.11907902 16 CHROMOSOME_I 63 1 100M * 0 0 CTACCCCGACGCCAAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #############################B==8>7BB>@B?@CDC@@CCBCC?@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3A0G2T1A3T86 NM:i:5 +SRR065390.18166736 16 CHROMOSOME_I 63 1 100M * 0 0 CTAATCCGAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################@?;AA>BB>B>===3BCBC@@CCDCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:4G2T2G89 NM:i:3 +SRR065390.24035073 16 CHROMOSOME_I 63 1 100M * 0 0 CTAAGCCTAAGCCGCAGCCTAAGCCCACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################################################A=CA?BACACBCCABCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCDC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:13T0A10T1A72 NM:i:4 +SRR065390.29735708 16 CHROMOSOME_I 63 1 100M * 0 0 ACAAGCCTACGCCTAAGCCTGGGCCTCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################################@B4B000+,1.+108;@BBBBBBB<@?B@>AB?BBB>>@?@>BBBB?:;>><:@@@? AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T6A7G2T5T7A12G53 NM:i:7 +SRR065390.1636136 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCC@CCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CACC@CACCAB:B?66@:@@@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3392236 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCBCBDCAABBDADDDBBABB@?A>BBADA?ACBBB@;?B;@?@@@<@6@@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6690334 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCBCBBCCCCCCCCBCCCCCCCBCCCCCC@CCAC>:AAA;9;==?=:/A=AA@?C?@A8757=?######################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13292986 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAGGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCC@CCCCCB@CD?C>C>@=A@5@A?AA?0=?####################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14309215 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCAACBCA:ACCADBABDDA;@BB<=::A>?B4;D69===D######### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.15577802 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDCCCCDACCCCBADCD@B>BB@BB3?B?BB>>B@AC?BB?>B?>?@@A@?B6AD AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16480523 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGGCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CBCCC??>CCC=ABBBAC;?AA6?@>@########################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:94C5 NM:i:1 +SRR065390.17141184 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACG @BBBBBBBB=>>>>>:>>>:<>>:>BBBBBBBBBAB:BB>>BB5BB9>>?BBB############################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.17760882 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACG CCCBCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCA@CCCCBA@CACC@CCC@BA>BCC@CBBCA><=CC@B@BB##################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.18662066 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCBCCBCCCCCDC@BC@AA=A5A=A@C=@@=?BB8A############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21809038 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAACCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCBCCDCCDCCBDCBDC?ABCBB?>B5=AA########################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93G6 NM:i:1 +SRR065390.22192818 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDCCCCBBCCDDDBBBBBBBBABB>B>BDB?AA>>@>@>9<48*@######### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23362845 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCC?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCDDDCBBCBDDB>BBBB?AABBBA6A>BB:>>5,=99?;6>=?####################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26775560 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCADCDDCBDCDB@B>BBBBB>>AA=<=@########################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:96T3 NM:i:1 +SRR065390.28745603 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCDCCDBABBB>BDB6BC>AA@BBDB>BA@B####################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29133277 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAATCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCDCCCDCCDCDBCBBBBCDBBBBCDDCCAABBDBAAA>@A@>D>A############### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93G6 NM:i:1 +SRR065390.4912040 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###@@A5:8A7;84:=>A:>;BB@>;BBBB?=@BDDBBCBCB>DCACCCBCCCBCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9629649 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ######################@A=>>;@@B;4BDB?BB5CCBB@>CCBBCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15607771 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ######@@=?<==:6<<>AA)B@BBA@BBBB>BA@BBCDDDADABCDDC@CCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16191081 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCBCCCCCCCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCC@A?CCCCCCCCCCCBC@CCCBB>A=@4=>@CC@@9@AA################# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16241777 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###############DBDD?:@1:@4=0=;>8B>@CC<@=CACCCCCCCCCBCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22359834 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG @=)????<6>A>AAADBDD>;>>BBC;@BBAB;ADBBBBADBCB@@CCCD@CCCC;@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25076320 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###################################@:=C>@D=CCDCCCCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26013356 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###############?C>CBBA=BBDDBBABDD@DCDACDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29257811 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###############@9@@=:@?BB>;B?BB>>BBDBD;CBCDAACCCA>?CACC?CCCCCACCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29430375 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCBCCCCDDCBBCABBBBBBAACCAAAABCBAAB?AAA6A@A@>?AAAA?64?########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30148213 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCC=@@B@A<@@;BB=BB;BBB>>?B@?@4;@############################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30863885 16 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ####################@@@@@>>DBB>6BBBC@BDBBA=BBBBCDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31415192 0 CHROMOSOME_I 64 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDDCCBCBCBCDD@C;@@C@BBB@BAB>BB@82>>=AB;B?@B>6>77=7*;,7378/895A?AB< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6076202 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCDCACDC@DCABB>A>?@>??,>?=A########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6192585 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBDBCBABBDDB@BDDD@B>BAB?@ABABB?C?:AA@=)?:=@@####### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9007991 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCACCCCCCCCCCCCCCC=CDBC@AB>B5<@==BBB>B>?BBB20879=(5:.=:@94 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12321086 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDCDDBDD@DDDDBDBBBBC=>B>BBBACCBC>CCAC?ACC= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20771747 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA@ACC@DCDAC@>@BBBB??B<<7739373:93937;3=@A>?A?A96<*8:5<8@############ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21858348 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCDDDABDBBBBBBADABBBA4>BB???######################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22848365 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCBAC@CDADB;DDBB@@@?BBB>BCAACAADD??A>A>>40771 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25705771 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCDDDBBCDAD>DABB>BCA=@:@?@A?*=70;70=@@A@######################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12439940 16 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ##DDB6@<<=D6B>@BB@@ABDB@@B@BB=D@DBDCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14000986 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCBACCCDD@CBDDA@DDABBADBDDDDABBBB;DBBBBB>CABAABAACA:BA:?B?6?ADD? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16839733 16 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #############################################AA@CC;CCCCCCCAABA@CCCCA@C@CC@BCCCCCCAABAA@AACCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17727634 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAACCBCBDCDDACBCBBBBAB@>BBB@BA@B?;BB@A6?A8?################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19208569 16 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #########?979-5A:.6@B?>6BABCA;=DDDB=ACCBDCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22372328 16 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ####A5*904@6=@>1BBBBBBCBBBABCDCCDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23208723 16 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ######@==B:77.<<@=<::>=:7;6BBBDB4BBBB9=BCA@B;CCBCAABCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24356433 0 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCDCBDDBADDBB;BBAABBABB>C6AB??>*AA@:A8@@@###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.33542765 16 CHROMOSOME_I 65 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #######A6@>:AAC=AA4A>;@DB>=@8<@BBBDABBDDA@B:?0?############################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12905806 0 CHROMOSOME_I 67 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCC@CCCCC?ACCC<@CBBBA5CBDA@=A@=@A><@>BB8BB>BBD3D###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17964782 0 CHROMOSOME_I 67 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCAABCB=8BB?BBB>AB8<=???0;7?######################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24880161 0 CHROMOSOME_I 67 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCADCCCDDDDDCBAABDBB>D>B@BD?D8@==A==@@>;;: AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29470600 0 CHROMOSOME_I 67 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCADCA@ABBBAB=BB<=A=BDD:@BCACAC@@############# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:95A4 NM:i:1 +SRR065390.9712286 16 CHROMOSOME_I 67 1 100M * 0 0 CCCTAAGCCTAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##############################@AA@A::=>/==:A>B@DCCBBBBCCC>CDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0G17G81 NM:i:2 +SRR065390.9802725 0 CHROMOSOME_I 67 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCDCCCCCCCCCCCBCCCCBCCCCCCAA@CCCCCCCCCCCCBCCC?>AAA=>AA3>AA8=AC>A=CAC?>?B?B@B#################### AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:58A41 NM:i:1 +SRR065390.4151860 0 CHROMOSOME_I 68 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTA CCCCCCCCCCCCDCCCCCCCCCCCCCCCC@7?<A:=;A27>22@37???A6@A:9;-390=754:=@##################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93A6 NM:i:1 +SRR065390.6451314 0 CHROMOSOME_I 68 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCBCDAACDABBBDD@B=BDBB;A7A???#################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93A6 NM:i:1 +SRR065390.7753919 0 CHROMOSOME_I 68 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGTCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCBCCBCCBCA?>*>??@?:B>CCC>CCCDBB>DB@B=6BBBB=1=A?9:D8D@@?@8 AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:48C51 NM:i:1 +SRR065390.12766808 0 CHROMOSOME_I 68 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCC@CCCCBBCB5>@?@B@B@97;;9@################################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98T1 NM:i:1 +SRR065390.27353147 16 CHROMOSOME_I 68 1 100M * 0 0 CCGCAGCCTAAGTCTGAGCCTAAGCCTAAGCCTAATCCTAAGCCTGAGCCTACGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #############################################################################################B>==@A? AS:i:-16 XS:i:-16 XN:i:0 XM:i:8 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T0A8C2A19G9A6A6G40 NM:i:8 +SRR065390.2141529 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCCADAD@B>B>@@@D?BABB>?BA?########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2320480 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<>CCCC8@CCCC=ABCCBACBC9=CB@:C56@8A.:5?=3A?B@B@?>?B?;;434=>90>: AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4714421 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCBADBCDDCDBDCBBABDAC@BCBAAABBB?AB>=BDAAA?BD;?B?@#### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6640654 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCC@CCCCC@CCCCCCACCCCCCCCDC>CCCC>CCDCCABADCBD;B@BB=B?=B>19>==@>4BB8:=74B;?8D??8@########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7630109 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCBACCBDAB@DAABBB@B?@########################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9514930 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB@CCDB@BAB@A@>@B=>>4A???8BBD??9D@>?;?85@####### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10004235 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCACACCDCC@CD@AB@@C>BC;:@?:@=??########################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10865454 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDC@CD@BB?CB@BDDD@BAA@AB3>?>>==(9:;=4>@:@;:27.@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12673297 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCDCCACCCC=CACBA>DCDDCABBDB@>>B>B@>B@AAA>C>3@=:@@A>?########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12772245 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CACBBC@CCABC;CACBCCBA==B>?=A#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13667706 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCBCCCCCCCCCCCC@CCCCCACCC?CCCCC@8AAA:@:>:BBB;B@=?B?BDB0BBD@B>B>=BD,//85A4AA@CAAAAAAAA??8?@@@@?########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17659493 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCA@CCCDBCCACB@BBDBDA=BBABB=AACA=@?B####### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18370296 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDC>CCBA>BC>BBDBB>B=8BBDCAAAA>8?:?A?:?DAA>A###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18372281 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCDBDDDBBDBDBBBB=BB;BB@BABBB>?BA?A>CAA@CCCACC>CBA>DCDB@A@BB@C@BBCA=>=:@##################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31254323 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCDBCCACCCCBABDBDBBAAB>BBBBBA?BBB>AABAAA??BB@9(AABDA>B@BB>BA8BB>:>8@=>6@3:<@=@:@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11515609 16 CHROMOSOME_I 69 1 100M * 0 0 CCAAGCCAAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############################?>55;C<CCCC@@82@A=A;=@8?C@C@@CCCB@CCCCBCCCBCCCCCCCCCACCCACCAC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T5T92 NM:i:2 +SRR065390.11752838 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBBCCBABBBD@BAB=BB?B=3?@@=?@:B>:A########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11823969 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCBCCCCCCCC?CCACC>@C@CA?BC?AB;@@@@DB=ABBBBAD@BBB;AABBCAAABAA=A>A AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12248467 0 CHROMOSOME_I 69 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCCBCCCCCCCCCCCBDD@A=A>BDD>>>BBB@BB>B3BB?@;:>=+<55,75=::AA@6@## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7434339 0 CHROMOSOME_I 70 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCAAAGCCTAAG DBCCCCCCCCCCCCCCCCCCCCBC@CCACCAAB?ACCCCBA>BBBBA>>AD@B@?>@@A########################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:84A8C6 NM:i:2 +SRR065390.23718480 16 CHROMOSOME_I 71 0 100M * 0 0 ACGCAGACGCCATAGCAGAGGGGTACGCCTCAGCCTGAGCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ############################################################################A>4@AA:?A@;A6>00000763:6 AS:i:-30 XS:i:-30 XN:i:0 XM:i:15 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1A2C0T1A3T0A3C0T1A1C0C2A4A5A6A56 NM:i:15 +SRR065390.21251465 0 CHROMOSOME_I 73 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCACCC@CCCCB>CBCDB=@7?5@@>:>@=??/=?############################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:94A5 NM:i:1 +SRR065390.21597469 16 CHROMOSOME_I 73 1 100M * 0 0 GCCTAAGCCTCAGCCTAAGCCTAAGGCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ####################################BBABC?CDCCC@CCCCACBCCCCCCCCCCCACCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:10A14C74 NM:i:2 +SRR065390.29344619 16 CHROMOSOME_I 73 1 100M * 0 0 TGATAGGCCAAAGCCTAAGCCTAGGCCAACACCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #########################################AA?A897+99>;7:0A>>8BABABB?ABBAABA8><>9>808<8 AS:i:-18 XS:i:-18 XN:i:0 XM:i:9 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0G0C0C2A3T13A3T1A0G69 NM:i:9 +SRR065390.32874267 0 CHROMOSOME_I 75 1 13M1D87M * 0 0 CTAAGCCTAAGCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG DCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCC@CCCCCCCCCCCCCCA>/=;=9>:/5AA############# AS:i:-8 XS:i:-8 XN:i:0 XM:i:0 XO:i:1 XG:i:1 YT:Z:UU MD:Z:13^T87 NM:i:1 +SRR065390.13205982 16 CHROMOSOME_I 75 1 100M * 0 0 CTAAGCCTAGGCCCAAGCCCAAGCCTAAGCCTAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################################################################################################### AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:9A3T5T14G65 NM:i:4 +SRR065390.1968887 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAAGCTAAGCCCAAACCTAAAGCTAAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCC@C==@=:A####################################################### AS:i:-16 XS:i:-16 XN:i:0 XM:i:8 XO:i:0 XG:i:0 YT:Z:UU MD:Z:72T2G0C7T2G5G0C4G0 NM:i:8 +SRR065390.3020042 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTACGACTAAG CCCCCCCCCCCCCCCCCCCCCC@CCCCACCCCCCCCCC@CCBCCCCC=CCCCD8CCA########################################### AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:82C9A1C5 NM:i:3 +SRR065390.5329842 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAGGCCTAAG CCCCC@CCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCC@CCCCCCCACDCCCCABCCB0@>A@?BBD@B>BA>B>B??BBAAC>?=:?A########## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92A7 NM:i:1 +SRR065390.7718336 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAA+AAAAAACCCCCACDDCCDCCBD@B@BBBD<;@BBB?BACBBB8D>B>B)>? AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:48T51 NM:i:1 +SRR065390.9099421 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCAAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCB@C<@@BDCA@D@;B@A?=@B########################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:84T15 NM:i:1 +SRR065390.13504888 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAGCCTAAG CCCCCCCCCCCCCCCBCCCCCCCCCCCACCCCCCCCCCCCC@CCC=;3=ABB=@B@?@B<@################################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:87G12 NM:i:1 +SRR065390.26299881 0 CHROMOSOME_I 76 0 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCACAAAGCTAAACGCATC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCBDBBDDDABBDD?###################################################### AS:i:-20 XS:i:-20 XN:i:0 XM:i:10 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80A2C0T2G0C4G1C0T1A0G0 NM:i:10 +SRR065390.26546478 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAACCTAAGCCTCAGCCTAAC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@DCAACBBC@CC@BCBDD=BB>;BDDB>?################################### AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:78T2G9A7G0 NM:i:4 +SRR065390.27871278 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCDDDBCC@@B@AD@BDDC=BBBB@>;@BAA################################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:90T9 NM:i:1 +SRR065390.28581901 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCATAAGCAAAAG CCCCCCCCC@CCCCCCCC@C>>B>>C@8CC@CC@@@?A######################################### AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:89C5C0T3 NM:i:3 +SRR065390.30916163 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACG CCCCCCCCC9CCCCCCCCCCCCCCCCC@AC>?<;CCACCCCCB;C@@===;=BBB0A=A################################# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.32781383 0 CHROMOSOME_I 76 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCAAAG DCCCDCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCC@CCC?CC?CCCBCCDA@BB?BB3B>BBDADBDCACCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0T2G0C95 NM:i:3 +SRR065390.7469639 0 CHROMOSOME_I 77 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGC CCBC?CABC>CCBCCACACCCB?CCC@ABCCCBDCA@C@BCB=@<@@##################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:85A14 NM:i:1 +SRR065390.13605737 0 CHROMOSOME_I 77 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGC CCCCCCCCCCCCCCCCCCCBCCCCCCACCCCCACCCDCACCACBABB@B<>BB>B:7;=7=><<<<>A=:?A.@@######################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:95T4 NM:i:1 +SRR065390.14866698 16 CHROMOSOME_I 77 1 100M * 0 0 AAGCGTAAGCCTAAGCCTAAGCGTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ########################################C>3CCAABAA3AA?ACCCCBCCBCCCCCCCCCCACCCCCCCCACCCCCCCCCCCDCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:4C17C77 NM:i:2 +SRR065390.19434606 16 CHROMOSOME_I 77 1 100M * 0 0 AATGCTATGACTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ##############################################@:A80000/=09;?5>>>;AA5A>?CCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2G0C3A1C90 NM:i:4 +SRR065390.30084692 16 CHROMOSOME_I 77 0 56M3I41M * 0 0 GCGCGTAGTCCTCATCCTCAGCCTCAGCCTAAGCCTAAGCCGAAGCCTAAGCCTAATAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ########################################################BA76CCB>B@ACBCA.>?ACC5CCCCCA;CC@CCCCCCC>==?=?@BC@@BCCCCACBACCACCBB@>BA=5BB############################################## AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:79C13T3C2 NM:i:3 +SRR065390.29958565 0 CHROMOSOME_I 79 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAACCTAAGCCTAGGCAGAAGGGCAAGCTC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBCCACCC=BDDBA>@@@>B################################ AS:i:-18 XS:i:-18 XN:i:0 XM:i:9 XO:i:0 XG:i:0 YT:Z:UU MD:Z:72G10A2C0T3C0C0T4C0T0 NM:i:9 +SRR065390.26894079 0 CHROMOSOME_I 80 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCDCC=CCACB;BBBB>8A8AA?=<>:?=8=A?@=D?D=B@B########################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:91A8 NM:i:1 +SRR065390.15628724 0 CHROMOSOME_I 83 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCC00000+0//000000CCCCCCCCCDCCCCA@@BCCCADCCCB;8@BBB>;BBBB@;AA?A749=>:=*9=>@::A?8=3@##### AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:20G79 NM:i:1 +SRR065390.4058482 16 CHROMOSOME_I 83 1 100M * 0 0 AAGCCTATGCCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ############################BD:?2;@?24?6?3??86?3?:B>@BB87787>BBBBBBBBBBBBBBA????>:BBB?CACC?C@C@CCC@@ AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:7A3T88 NM:i:2 +SRR065390.31993990 16 CHROMOSOME_I 83 1 100M * 0 0 AAGCCTACGCCTAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ###########################B9;13>54888@@<@9>>7>7:@A@><8<68@@##################################################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80T15C3 NM:i:2 +SRR065390.268023 16 CHROMOSOME_I 86 1 100M * 0 0 CCCAAGCCTAAGCCCAAGCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #########################################@@B?>?;BBB>>CCC8CCDCCC?CCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T11T7A77 NM:i:3 +SRR065390.6919046 16 CHROMOSOME_I 86 1 100M * 0 0 CCCAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ##########################################BCBAB=BCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T8G88 NM:i:2 +SRR065390.2121410 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ######################?BA;;=:8CDBABDCDA@ADCABDACCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6166783 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##########BB?A?B>BB@>@CABABBA@@@BBDADB@BBCBBADCCBDCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7495357 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA B3>6BB=?>BBB4?@>@BBBB;@BBBAB=BBA@=AADDCCCCCCC@@CCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11353312 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################@7?;<@BB=6>BB?@A@@B;B@BACBDD@CCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15848524 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA 77471AAAAAAACCBAABB>BBDBBDBDDDADDCC@>?@6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15965869 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #######@7.@B>>?@??@@:,9;3=<:8@>ABB=BBB@>ABBAC:CCCCD@ACCCAACCCCCC8CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17210890 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA D>:>DDD*>?BDB?;BDBB@>BBBB@>DC@CCBAB?CAB@DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17578845 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA B:=@@1BAAAD>B???@???==;@A=@AADC@ACCCCB=CBCCC@?DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21562505 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################DBBBBB@>BCB=D@ADCBABCCCBDCDCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30807379 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################@@;852A>:?A;AB>C;ABBAB>CBBBA@BBDBBACDDDDB>CCDCCDCCBCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32276242 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #########################?9>=AB@?@BBDA6DDBCDDBCDCCDCCCCCACCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.33628207 16 CHROMOSOME_I 87 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #####@B@9@77=74>6BBD;?B?B<@>DCBDABBAB?B@ACC=CCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25375430 0 CHROMOSOME_I 88 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCCTAAGCCTAAGCATAAGCCTAAGCGTAAG CCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCBCACCDBDBBDA@@BC>B@>.?A??<1@########################## AS:i:-7 XS:i:-7 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:66T16C11C4 NM:i:3 +SRR065390.7789978 16 CHROMOSOME_I 88 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGGAGCCTCAGCCTGAGCCTAGTCTTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###########################################################@C?A@C<;;;5;;;65AACCCCC@CCCCCCCCCCCCCCCCC AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:30T0A5A5A6A0G1C46 NM:i:7 +SRR065390.22922524 16 CHROMOSOME_I 88 1 100M * 0 0 TAAGCCTAAGCCTAGCCCTAGGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ##########################AA?:CBABABBDBB<;ABBA@@>8BC=>BCBCBACCACCCCADCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:14A0G4A79 NM:i:3 +SRR065390.30422609 16 CHROMOSOME_I 88 1 100M * 0 0 TAACCCTAAGCCCAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###################################################?CCCCCC?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3G8T26G60 NM:i:3 +SRR065390.3148788 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCC796B@5B=5=@=:*=>><<8@############################# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3974764 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCBCCA@CAC@A@DDADBCBAA@BCCBBBC=BCBB>?==>>=??@A@@?@########################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8437156 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCACCCCADCCCCCCCCCDDDCCCCA@B@B@BACAB?@BB>BBA>B=>?::D>??B8@?:@######################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12974063 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCDDACBCB@;@BD@?@@@>@@@@??(@######################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17247283 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCABBCBC8?AAAAA>B@BCABB>BB@.=@BA=>==BB@B@########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17845387 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCACCCCC8CCCBC;BBBBAAADDDC>BDD>AA@BC?CA>CA>A;0500=A:?AB AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19019558 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCBDCCCDADC=B>BBBB;?BB>B>BB8A=A<=@############# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20644304 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCC;ACCCA8ACCC<8@4@@@5?>@@3?###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29723571 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCDADDBDA@BDBDBBCB>BB>BC>>A;@@3D>??D;?#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30710022 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCDCACCCDDACDDBDBDDDBBABBBCB6BBBAC;>AAAAA?AAAA>??@?########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.33685608 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDCDBBBBCBABBBDBA:;=:<;=AAAB?@=CBB@=C<@>B;@B:A>;BD>AB=@BBD@DAABABCCDDCCACCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15212051 0 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCDCCCCCDD@CDC@DDBB@BDACB?BB=@B=B?D?B5=::A#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18095819 16 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ################@B;DDBBB;BBDDB>BBDCB=DBBCBCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20762057 16 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ####?7:88;:7@.=>>>BBCB>@D>DB=BDBDDDBCDBBBDCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21120770 16 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ###########################@@?A?A@C@B@BAC@@?@CCACBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23419512 16 CHROMOSOME_I 89 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ###############?=;9:5A?@@2==9=270;7AB;:BDDCBDDDCBCCCCCCACCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25957119 0 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCGTCAGCCTAGGCCT =BB?CA@@@C7?;<<;>CBCCCCCCCCC8?C@CC?@@B>>2B7888*.0000@====;80==.;?;2?######################## AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:81T4C1A6A4 NM:i:4 +SRR065390.256433 16 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##########################A>9=;BCA?BBBC@0?@>DB?=B@BBCCC>@ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6797268 0 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCATAAGACTAAGCCTAAGACT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCC@AAAAC@CB?@@?@C;15<@9=7/7=<<>@B@B@##################### AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80C4C11C2 NM:i:3 +SRR065390.7161425 16 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ####################?8:@2@B;?@B@B>@DBBCB@DABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10403193 16 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT 7:;72=9<=:4@@?A?5?>BDC>BB?@>8:??@B9BBDCD>@BBCCCC@ACCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14326039 16 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##########?<@??>B1ABABB>BDABBB=ADBC@ACCCBC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16063981 16 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT 7@7:7+>:=9@@B@=D>4B>@B6@B>B=<>DA@DABC=AC@BC=CCBCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20404151 16 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ############?<>A?<<=73:55235124813808A?>8237:=;9?A000/000000?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24289923 16 CHROMOSOME_I 91 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ###############################AA>A=@A@@@B;CCB@D>CCBCC@DCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28545477 0 CHROMOSOME_I 93 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTAA CCCCCCCCCCCCCCCCCCCC@@B@ACCBCCCCCCCCCCCCCCCBCBCC@C;?:7:::@>A>@>B>;@=A: AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3687468 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG BCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCBCCCCCCCCACCCACCCCCCCCCABACCCDACA>@@:@############################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6194634 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCC@CCAACCCC@CACCC?>ABBC=@@1@CB=CB6><@88:377;ABBBB##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6316515 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDDCDACBDDBDDBBDB>A>?B@?@5@???##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7638809 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CACCDCADACBACB@CDABB@DBB@@>B>B>B=BAAC>>@:@@@5;79@########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12817194 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCBCBDCCDCCBCCDDAABBB@DBCBDDD@DBB@CB>C= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16588016 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCD@C=CCCBCDC@BBCB@?A@A?@>BDBBB>BAA):=:7D@@D? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21115573 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCDCABDCDD@ABBBB@=BBBA=DBBBB;>B?D?6>B?D?############ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22487510 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCBCCADBBDDABACBB=AA?@DDBA:BD?A??B::==::9:*>@############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9644932 16 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG 77=9==5845?A=??AB@@3BB@CAB;CCCAC>CBCDB@CCCCB?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12890063 16 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ######@(<9?B4;B:A@;8?BBB9B@>BDB;DBDCCADBCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16020961 16 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ##################?:B*B@@?>?:?57=36C>@@AA=63ACC@CCCCCCCC@@CCBBCACCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28179307 16 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###############?.?=@:B@??@@@@6?B>B?CBA;DBBBB;BBBBBADDBDDBCDDDDDCCACDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28514209 0 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCDCCACCCCCACCCCCCCCCACDCCB@>AABB>=B?A??=BBB>B8=>>8><@?62;B=@############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29025503 16 CHROMOSOME_I 94 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ##########A@63@;CCAC===@=>B?BBBB?BBBABBDBCDDDCDBDBCBCCCBCBCACCCBCCCCCCACCCCCCCCCCCCCDCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25192538 0 CHROMOSOME_I 95 0 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGGCGAGGTTTAGCAGGAATGCCGAGACTGATACGACAACCCAGCCTCTGCCTCAGC AAAA>?A>A?@@B@>>?=>?58:>:AB<>B>>:B################################################################## AS:i:-56 XS:i:-56 XN:i:0 XM:i:28 XO:i:0 XG:i:0 YT:Z:UU MD:Z:42A2C1T1A1C0C2A0G0C0C0T2G0C1T0A2C2A1G0C1T1A0G0C1T0A5A0A4A3 NM:i:28 +SRR065390.28309751 0 CHROMOSOME_I 95 0 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAATCCTACGCCTAAACCTACACAAAAGCCTAAGCCTAACCCTAAAG AA>AACCCCCCCCCCCCCCCACCCCCACCCC5BBCCCCABDDDDBDC>@B################################################## AS:i:-20 XS:i:-20 XN:i:0 XM:i:10 XO:i:0 XG:i:0 YT:Z:UU MD:Z:56G4A6G4A0G1C0T14G5G0C0 NM:i:10 +SRR065390.28547696 0 CHROMOSOME_I 95 0 77M1I22M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTAAGCCTAAGCCTAACCCTAAACCATAGGACAACGCTAAAGCCTAAC B?CCCCCBCCBBBB=@BB:>:>B>@B>BBB@B<@@B@=ABAA;>>B?D>DAD################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10373067 0 CHROMOSOME_I 96 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCDCCCCCCCCCCCCCCCCCCACCCCCCCCCBD=CCCCCC?CA??<=AB<=A@A@@6A?AAB>@?B@B;B>?8DD>AAA>?>????3>8989A=;4A?;8;17888@############################################# AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:86C5C3A3 NM:i:3 +SRR065390.14825713 0 CHROMOSOME_I 96 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCBBAAB@AD@BA=BBB=ABABBC@4>B=5=>AB>DA5<@@@86@=@< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15608785 0 CHROMOSOME_I 96 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCBCCCCCCCCCBCDDBDABBB>BBA@B>ABBABABBB>A4B=;9>5AA######## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29977405 0 CHROMOSOME_I 96 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCDDCBBBDDDDBDDDDDAADBBDABAABB>ACCBC>:<@@@##################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7301839 0 CHROMOSOME_I 98 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTACGAGTAAGCCAAAGACTAAGACTA CCCCCCCCCCCCCCCCC4>@################################################################################ AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:69A6A1C0C6T3C5C3 NM:i:7 +SRR065390.253303 0 CHROMOSOME_I 99 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCB?BC@=CCBC@BBC?;@############################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:89C9A0 NM:i:2 +SRR065390.1116804 0 CHROMOSOME_I 101 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTATGACTAAAC 0000089938?:?>8:8:<>785;;@3@@@######################################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93C2A3 NM:i:2 +SRR065390.15284472 16 CHROMOSOME_I 102 0 79M3I18M * 0 0 AGCCTAAGCGTATCCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAATAAGCCTAAGCCGAAGCCTAA ###################################################A9<>>>BBBB>BBB>>88>/???89B>BBCC?CC00000:9:<;@B?CC AS:i:-24 XS:i:-24 XN:i:0 XM:i:4 XO:i:1 XG:i:3 YT:Z:UU MD:Z:9C2A0G74T8 NM:i:7 +SRR065390.32407240 16 CHROMOSOME_I 102 1 100M * 0 0 ACGCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ######################################A=::@@A853;200*.054B5?=0=AA3338900.0/CCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1G0C97 NM:i:2 +SRR065390.2751803 0 CHROMOSOME_I 105 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCGAAGCCTAAGCCTAA BCCCCBCCCCCCCACCCCC>CCCCCCCBCBCCCCCCCCCC==:AA@CCCCB=BC:+0100C?CC?######################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80A4T14 NM:i:2 +SRR065390.9101383 16 CHROMOSOME_I 105 12 100M * 0 0 CGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###########################################################A<7?<1?CCCC@ACBACAC?CCCCCCCCCCCCCCCBC@CCC AS:i:-6 XS:i:-18 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T35T0A61 NM:i:3 +SRR065390.19805019 16 CHROMOSOME_I 109 1 100M * 0 0 GCCTGAGCCGAGGCCTAAGCCGAAGCCGAAGCCGGAGCCGAAGCCTAAGCCTAAGCGTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #################################################################C>C:CCC@CC@CCCCBBCCCCCCCCBBCACCCBCC AS:i:-18 XS:i:-18 XN:i:0 XM:i:9 XO:i:0 XG:i:0 YT:Z:UU MD:Z:4A4T1A9T5T5T0A4T16C43 NM:i:9 +SRR065390.634578 0 CHROMOSOME_I 110 0 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCATAAGAATAAGCCAAAGCCTAAGCCTACGCTTACGCTTACGCCTATGCCTA >@C@@CCCBCCBCCC@B@5BAAAAA@BBBBB@BBAB(BBB?;;;?####################################################### AS:i:-20 XS:i:-20 XN:i:0 XM:i:10 XO:i:0 XG:i:0 YT:Z:UU MD:Z:49C4C0C6T13A2C2A2C2A5A5 NM:i:10 +SRR065390.14445465 16 CHROMOSOME_I 110 1 100M * 0 0 CCTGCGCCTAAGCGTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ##############################C?BBB=AAA:'000(0=AAA>?CCCC@8@BCCCCCCCCCCCCCCCC?@C@?CC@BBCCCC@C@C@CCCC AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0C8A0A3T12A72 NM:i:5 +SRR065390.19877275 16 CHROMOSOME_I 110 1 100M * 0 0 CCTAACCCTACGCCAAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ##############################@=9==(B?<B>B>>B>>>A>B>BBB<>BB888:;00./0::72;CCCCCCCACC AS:i:-16 XS:i:-16 XN:i:0 XM:i:8 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3A0A4A4T0A5A0A4A72 NM:i:8 +SRR065390.4419 0 CHROMOSOME_I 111 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAA CCCCCCCCCCCCCCBCBCCCBCC8CCCC?C@CCCCC@CC@C@CC8C?@5BCC@;@CA>@@=:>>532:;8A@A@########################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92A7 NM:i:1 +SRR065390.6629332 0 CHROMOSOME_I 111 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCADCACCC@B=ACBBB=CBD?@BB>B@DB>>.>=>>*4;77A@?A>DB<:?=@@,8 AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80A19 NM:i:1 +SRR065390.13561281 0 CHROMOSOME_I 111 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCADDCCCC?CCC@CB8?*?:7==8==@<@:@######################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:97T2 NM:i:1 +SRR065390.13848363 0 CHROMOSOME_I 111 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCBDCC@CCAA?DCBBADBD>>>BB>>B1DAB;B6B9DD###### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:99A0 NM:i:1 +SRR065390.15692749 0 CHROMOSOME_I 111 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCC@CCCCB@BAC??>B@B@B?<:??C8@?A8A####################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.27886908 0 CHROMOSOME_I 111 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCBBBDBD@BCBBAB@############################################# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:56A43 NM:i:1 +SRR065390.32433607 0 CHROMOSOME_I 111 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCDCCCD@BBCB*A:A?:@BBB?BA@BA;BBBBB=B>>B@;=>;<::82>8<59 AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:58G41 NM:i:1 +SRR065390.32577253 0 CHROMOSOME_I 111 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTAAGCCTAAGCCCAAGCCTCAGATTAAGCCGAG CCBCCCCCCCCBCCCCCCCBBCCCCCCCC=CCCC?CCCCCCCCCCCCCCBADCCDACABCD@DAB@BBBBC@AB@@################################# AS:i:-5 XS:i:-5 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:6C93 NM:i:1 +SRR065390.27208864 0 CHROMOSOME_I 112 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTAAGCCTAAGCCAACGCCTAAGCATAAGCCTAAGCCTAAGCCTAAGCGTAAGCGCAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCC?####################################################################### AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:41C12T1A8C23C5C0T3 NM:i:7 +SRR065390.14809419 0 CHROMOSOME_I 114 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCC=CCCCCCCCDCCCCCDCCDCCBCBDCCBDBBCDBDB>BDABAABBC@BCBBC>>A?B?B>?AAA>A4A=9@####### AS:i:-4 XS:i:-4 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:22T77 NM:i:1 +SRR065390.20842573 0 CHROMOSOME_I 114 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCC@CCCBDDBCDDB>D@A==:9@256&(3036-@@@3@#################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:68C31 NM:i:1 +SRR065390.349756 0 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC@CCCB=B<>BB@= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8856958 0 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCC@CCC?CCCCCDCCBDCDDBCA?>AA@@?BB?;B::2=4=B################################# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19124748 0 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCCCCCCCCC=CCCCDBCCDDACCB<<=@?B@6@?BB>B>?>9>(:=979A#### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23327180 0 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDCDCCBBABA@@B@BB6BB@BAAAC?CAA>=@@<(@########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24595212 0 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCACDCCBB@DDDAA>DBDBA;AABB?6DBD>?=??B>@9<:=<;46@@@:@############## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.802879 16 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ###############?05@@@@;BBAA=CCCBA6@@CCCC?CCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9215590 16 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ######?=?:@6B@@C<=A?A?8@@B@B@@B?8CBCDBB;>==BDADDBDBADBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13357175 16 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT B>::@@D<@??:?DB?B;D>BAB=B@DB>@DDBDBABBDC@ACACCDACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13460510 16 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #########################C@<B>B@@@@8BCCDD>ACDBCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24138882 16 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##############################@?BA?<;BCBB@ABC;DBA@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29591166 16 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #########################@@<81=@@<BBBAADDBDBDDDCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29698542 0 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCCCCDCCACCBCCACABAABCBABBBB@A@?@AAA?####################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30439372 0 CHROMOSOME_I 115 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD@BBBCDDABCCBCDBC>BA@DABB>BBB;>BABABB>B?>ADB>B AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6134052 0 CHROMOSOME_I 116 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTACGCCTAAGCCTAAGGCTA CCCCCC@BCCC@BCBBB>@B9<;88@@:@:8778;88;;>=:3@@76384@<@@############################################## AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:74T7A13C3 NM:i:3 +SRR065390.10167659 0 CHROMOSOME_I 116 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCATAAGCGTACGCCCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCB=;ACCC@=AACC=?@@=@;(?@?################################### AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:85C5C2A3T1 NM:i:4 +SRR065390.14472485 0 CHROMOSOME_I 116 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCGTAAGCCTA CCCCCCCCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCDCCCCDBDCDDDDCBDDDCDDBBBBDBBBAABD>DD3:=>A><==A################ AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:86T4C8 NM:i:2 +SRR065390.16076532 0 CHROMOSOME_I 116 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGCACGCCTA CCCCCCCCCCCCBCCCCCCCCCCCCCCCC@BCBCCCCCCCCCACCCCCCC?CCCC4;???@=B=C?A?A;??<B;==?############### AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:91C0T1A5 NM:i:3 +SRR065390.28531075 0 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAC BCCCCCCCCCCCCCCC@CCCCCCACCCCCCCCCCCCCC=CACCCCCC@BDCC################################################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:99A0 NM:i:1 +SRR065390.32393251 0 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCCC@BCCA>B?CB@CBBBB=@B?BBB75@;<>BABBABBB@@CDAA@CBBCCDCCD@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2710794 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################A,A?@9A59>;<1@AB<@5=BC9;9:3CCCCCCCBBCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3026627 0 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAA CCCCCCCCCCBBCCCCBCCCCC@CCCCCCBCCCCCCCCCCCAC?CC?CACCBBCCAC=?@@@?@BBAB@C############################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:97T2 NM:i:1 +SRR065390.4690010 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ;=<@@9355*;B@@B>B>BB:BBDBBB4BBAA;8AACB@@CBBC;DCCCDACCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4869028 0 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTACGACTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDCCBCBDCBBBBBB?########################################## AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:87A5A1C4 NM:i:3 +SRR065390.5729393 0 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGTCTAATCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCDBBDADDD?DDA?BD>B>CBBBBD:>2B#################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:89C4G5 NM:i:2 +SRR065390.7269481 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ############B??@@@@8>@BBB>BBDBBB>ADABBBCDDCBCCDCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10010220 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##########AA?==??>BBA6BB>B>;AB?DA@@DDBC@DCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10563492 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##########################################@:A@6@??AAC@C@?3B@?BCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11835411 16 CHROMOSOME_I 117 0 100M * 0 0 CCAACTCAACGCCTCTTCCTATCCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #########################################CCA=ABCCCCB@6CC@CCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-20 XS:i:-20 XN:i:0 XM:i:10 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T2G0C1T1A4A0A0G4A0G77 NM:i:10 +SRR065390.11890498 0 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB?CBCCCC@6>BA>>>ABC>>@DABBD>D@BABDDCDBCCBCCC@DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13274061 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################A91=:?B?D;BBB>AA=BBBB<=BCA@8AAB@CCCCCCC@@BA6>BBB@D@B?BB>BBABDAD@A@CCCBCCAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15182324 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA AA?>5BB?D;BABB=>BBBBAABB;DABDD@CDBCAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16508065 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA =297=@>>:@=?@:8B@BBBA=>BCB@C;CA8AC@AAACBCC@CC=4CACA;=@@###################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:87A12 NM:i:1 +SRR065390.16618625 0 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTAAGCCTAA CCBCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCC@CCCCCC@CA@A>?ABACCC?8A@AA=CB?AA@BB(??B=A*553;;8>?66:9:>+?;79 AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:74A25 NM:i:1 +SRR065390.16909890 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA A.=:@>>B8@B@B;BBACBAB@BCADBDCCCDDACCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17985359 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################A<48@B58=9=>=8=?B?>B3B=CDDBBB>@CDBCBCDDCCDCCCCCCCCACCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20428024 16 CHROMOSOME_I 117 1 100M * 0 0 CCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCGTAAGCCTAAGGCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ######################################################################################AAAA1/555/0000 AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T29T4C10C52 NM:i:4 +SRR065390.25333072 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #####################?B>DD?>BBBB;?>@BABBBACABBDDC@DBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26734455 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ################?A?@=;CBBA?>BAB>AABDDAA@DCDBBDCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26915421 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ####################@?=:6@;;7/4;5550>DD>>BBBB@B1DBBBB:;CABD?DC=AD@BACCACBCCDCCCCBCCCCCACCCCCCCCCCCCCCCCCBCCCCCCCCCBCBCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32532096 16 CHROMOSOME_I 117 1 100M * 0 0 CTAATCATAAGCCTAAGCGTAAGCCTAATCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################################################################A5?A000003699;:;<8:9;<99BC@CCCCCBB AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:4G1C11C9G5G65 NM:i:5 +SRR065390.33077092 16 CHROMOSOME_I 117 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ############?7=;?=A?>@BBA=@?DCCA@CACCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4104352 0 CHROMOSOME_I 119 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCDBDCCCDBACCCDACCCCBDBDDBD@BBDCBBBDBBBABBABBABA>BAC;>@>?####### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98G0C0 NM:i:2 +SRR065390.11335401 0 CHROMOSOME_I 119 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCCAAGCCTCAGCCCAAGCCCCAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCC@CCABCDBCACBBBCBBB:A>??C################################### AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:71T5T6A4T5T0A3 NM:i:6 +SRR065390.19440436 0 CHROMOSOME_I 119 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCGTAAGCCTAAGCCTATGC CCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=@CCC@C@BAAA################################################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:82C14A2 NM:i:2 +SRR065390.31062597 0 CHROMOSOME_I 119 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCCAAGCCTAGGCCCAAGCGCAAGC CBBCCCCCCCCCCCCCCCCCCCCACCCCCCC=?CCCCC?CC;;@@BBB@B@BC<@;;9>7@:=@@################################### AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:71T5T7A3T4C0T4 NM:i:6 +SRR065390.21240567 16 CHROMOSOME_I 119 1 100M * 0 0 AAGCCTAACCCTAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ########################################A::A48>,57/C6CC@CCBCC@CC?CCCCCDCCCCCCCCCCCCCCCCCBCCCCCDC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:8G11G79 NM:i:2 +SRR065390.473388 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CACCC@CCCCCCCC6CCCCCCDAB?@A=C;CA@=BA######################################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5212583 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCCBCBCDDA>BDBD=>?B>BB3B@B@@@DAC?C;>D:?<(79.:@<@@= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6106911 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CBCCCACCA?79878B@@?B78678B??>?>=AAABBBBA8A;>>B>:>BB<>?>;???######################################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7281918 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CDBCCBCDCCC@CDDDDBDBB@BBABB>AB@BD>B?85=797/@<:8 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14025609 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCC>CCCCD@BCDDBBCDAC?@A@DDABDA=D53885@?:A@@BDBB?3?>;=A######## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19641253 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAACCCCCCDCD@D@B@BD@B>BDBAB8>??A??;@B@D;?3==?B6?A##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20334733 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCACCCCCCCCCCCCCCCCC@BCAD?@@@BB@<1?################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22745112 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB@BDCCBCCACAAD=DDBA>B>@BB6B@AD?###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25556189 0 CHROMOSOME_I 123 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCDCCCCCBCCCCCCCCCCCDBCDDDBBBBBBBCBCBAAB@BBA@################################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.27641394 0 CHROMOSOME_I 124 0 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAACCTAACCCTAAGCCTAAGGCGTAACCCAAACCAAAGCGCAAGCGCAAC 88;68;;:;9@?>AA@CCCCCCCCCCC@CCC@C<>>>CCAC@A-@####################################################### AS:i:-28 XS:i:-28 XN:i:0 XM:i:14 XO:i:0 XG:i:0 YT:Z:UU MD:Z:51G5G12C1T0A1G2T2G2T4C0T4C0T2G0 NM:i:14 +SRR065390.9280611 16 CHROMOSOME_I 124 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG @@D=6@@6@@A?=ABABAA@B>=BCDBCDBBDBBDBDDADC=DCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12478066 16 CHROMOSOME_I 124 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #####B@@A?DB??@A:?AD=CBB>BCBBBADBBBDBABBDDDDCDCCDC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25264436 16 CHROMOSOME_I 124 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #######################@<766>><:4==:5==;C??@?=ACCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32908522 16 CHROMOSOME_I 124 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #############################@B=>><:CAB@=DCCAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24389795 16 CHROMOSOME_I 125 1 100M * 0 0 ACGCCTAAGCCTCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #######################################BBB=>DABB>BDCDDBBBCD@DCDCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1A10A87 NM:i:2 +SRR065390.7886550 16 CHROMOSOME_I 127 12 100M * 0 0 CCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #####?6@??AA;AAD:6@?A=CAC;;<;7<1B@@>BDDBB@B@BDBABBAB>>;BB8=;@BD::;>D#### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3825439 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCCCCDCCCCCBCCCCDDCCD@CBCCDDCBDBABBA@DBDBBBBCBBABBC>BAAA>D@######## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6176897 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCC@CCCCCCCC@ABCCAACCDCBBBA@ABABA@:@:??BBBA@DBAAAB>?B?:>B@@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6179290 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCDACBDCBABDBD@BBDDDBAAABBA>BCABB>A=4>>/=0298696=@##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9176327 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCC?CCCDDACDBDC>@BBAB=;?BBB4@@BD:3???5=:8>>9@:6@##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10096114 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCDCCDBCBADABDABBAA=B>B@?BD;4@7>9=7==>>> AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12408086 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBAA>DBDBB@BBAD=@?B?B?4A??B:A?AA<(@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15769247 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCACDDADDBA@B@BBBB>B6B?B@?########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16538618 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCC?ACCCCBCCCC@ABB@B:6BB8A?7@<><@:9?################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18630353 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCC@@CCDA?BBDBB@B@BB;@?BB>B;?<>=>69@:86A3=@@##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21703645 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCDDCCCA?D?C@CB@@B@@CDA@:==@@@<@@=?=>BCABA##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24795092 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCBCCCCCCCCCCCCBCCCCBCCABCACA<;;??C@;BBBD?6@@@@>2?@;8::>9>A11@###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31111380 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCDCCBDCBDCBDBBBDBDDBBBA@BBDBA@BBDDAACAB?:DD:??@><@<@@@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1774013 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###################@=379:@=??D>@<7D>>@B@DDB@;: AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3893380 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ####################A?0@A@=>8CCC@B=@CC?B@@CCAB@ACCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4975116 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #############B??8B?B8>>DB?=;8?BB@B@;BBB=>DCCBCABCCCCABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5530338 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCC?CCAAACDDBADBADDBBBAB@BB@;@B??################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6465879 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #####################?;@B;;>5A38;98BBDBBDDDC@BCCBCCCCCCCCCCCCCCDCCABCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6537766 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ################@8?=?D=6B>:==>?C;BBA5DBCB@BBAB;BCCBCB;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7401229 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCDCDCCCCDCCCCCCCCCCCCCCCCCCBBCB@CACABCBAA@BBB?=B;>B=5AA??@AB@=6=8=CC>AC;:??8;5/-51B>2A###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11449581 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA 7=741.8A;4B>>AAAB>AB?>B@BA@?A?/000(@AA>:C=;CCCCBCCCCCCCCBCCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11762556 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACDACBADDBADDBB@DB@BBDBBACBCCC>A??>?<8B### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11780901 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ######@@@@=<@@@68=>=>BADABBB6BB;BB>@CDBAA@CBBDADCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12246013 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCCCCCCCC@CBDBB@DBB@DBCBB;D@D?@B>?B=0=====;:@@@@@:@CCCCB?ACCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13762870 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###############A<>=@92757;;?8ABBB>B@A;BBB<>;B6B;@AAA;:BD:?@*5@@17@### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21762505 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #############?:1,@>B<<===>8@6@DB?@?ABBB@ABADBBDDBCDBDCBCCACCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21990338 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #############A=452==:=?=?@:?::@5?>=8:<=C?C@CCCCC@CB?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23838269 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCABCCDABDDCBABBBB>@=93=7=BBBB?0?:A=47@7@8/8<8@######### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24259901 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCBC@BCC@;CB@@BB><@@B@;;A??@:.?>9B:9>@@@(6=@####################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26950543 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #################################################A@B?@@CCACBCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28049981 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDCCDDCCCDBBA>B@>B>@?BDB@???<:?.75377?DAAA############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28919001 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #########################?:6>6@B6@@@B>D>AABBABDBACDADBBDDDDDBCDCDDCCCCAC@CDCCCCCCCCCCCCCCCBCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29600181 0 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBBDBDB?<@@6@?>9;9@############################# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29907490 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #########################@:<=2A8=B>6;A?@B@?>BC@B;CACBDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30476269 16 CHROMOSOME_I 128 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ########################@9/<22A?5:9@D>=D>A@BCAABDDBBDBCDBDCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9576969 16 CHROMOSOME_I 129 1 100M * 0 0 CTAAGCCTGAGCCTAAGCCTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###################################################AA=AA4A?AA.=AA;>7<>>58>>>71;<>;;7300000<>9>>@A??? AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:8A11A79 NM:i:2 +SRR065390.9988260 0 CHROMOSOME_I 129 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCCCCCCDA>A;C@=@;C@@@A@@############################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:79T20 NM:i:1 +SRR065390.10035310 16 CHROMOSOME_I 129 1 100M * 0 0 CAACGCCTAGGCCAACGCCAAAGCCGAAGCCTAGGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ########################################################A4?==:C?C>C@C@??><>@:@C@B@A@@CCCCBCACACC@CCC AS:i:-16 XS:i:-16 XN:i:0 XM:i:8 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T1A5A3T1A3T5T7A66 NM:i:8 +SRR065390.29366441 16 CHROMOSOME_I 129 1 100M * 0 0 CAAACCCTAAACCTAAGCCCAAGCCCAAACCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###################################################A=@A>@BBBDA=CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1T2G5G8T5T2G71 NM:i:6 +SRR065390.3937302 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCC?CCC?CCCCCCBCD?CCBCCBDC@CCB@==@A@@@B?8B?B?===?@?@A>?>A AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4086234 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAADCCACADDAB8@BBBB>?BBBD>B?BBACAB>BBA########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4778767 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAGCGGAAGCGTAAGCATAAGGCTACGCATAAC CCCCCCCCCCCCCCCC@ACCCCBCCCCCCACCCC@ACCAC=9CBCA<=?CA>=;BA@?########################################## AS:i:-18 XS:i:-18 XN:i:0 XM:i:9 XO:i:0 XG:i:0 YT:Z:UU MD:Z:58C12C0T4C5C4C3A2C3G0 NM:i:9 +SRR065390.8295829 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDCBDDBBCBBABBBBB==BB@@8@?@:>@@@A.:;8>A*<=8< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10871940 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDDBDDCCDBBBC>A############################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12095552 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCTCAC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDACCCBADBBC@4A)0.//A=>=6?>>:A>=@D99.@################# AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:84T12A1G0 NM:i:3 +SRR065390.13775982 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCC@CCDCBDADBC@DDBAB>BBB>=??@B@@?@>BD AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15558825 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAACCCCDCDBDBCDC@DB5BB@>@@;=A;?4@?############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16058509 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCACCACCBBCACC@DCBDC>CCABCBBC3===;DACBA;A:?########################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19900294 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCABACCDBDDABDABBA####################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19995334 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCBCCCCCCCBCCCB@BDCCBCCCDBADBBB@BBABBDAB@ADACD=>88A@@:=<>=A####### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21017432 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDCCCC@DDCCCDBA=AA=>>:?<@BB8>B############################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21103370 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBCCCCBBCDDCB;ABABB>?BB?@############################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23568099 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCDCCCC:ACCCAC>B>@@;C9=<8==BCAACCBB8;:69;37:5:3;9?########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24833775 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCDDDCBCDBDDBBDBCDA=DBBDBBB>BA6BA>BB??:??A?AAA@= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24981819 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCC?:CCBCCCCCCCBCCCCCBCCCCCC@CCCCCCCCCC@@CCC?CCC:C?CBCBC@BCB>@>@@.=9>9B@BB5@#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26074983 0 CHROMOSOME_I 130 0 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCACAAGCCCAACACTTACACCACG CCCCCCCBCCCCCCABCCCCCCC@CCCC>CCCCA@?CCBC3;A==<=;AD3BD;D@BB?=AAAA?>??###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28071689 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACBCCCCCACCBDCBDC>BADA?BB=A@>>8=48(;88/? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28757581 0 CHROMOSOME_I 130 0 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACACAAAGCCTAAACAAACGCCTATGCTTATTCAAAATCCTAAT CCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCC=CCC?C@8?>>>B>B5B################################################## AS:i:-30 XS:i:-30 XN:i:0 XM:i:15 XO:i:0 XG:i:0 YT:Z:UU MD:Z:57G0C1T8G1C0T1A5A2C2A0G1C0T2G5G0 NM:i:15 +SRR065390.29809470 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDD@CACDDADBDAAADBDB>;DBBB>BBABAC>ACB@3@@6:95*@########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32683144 0 CHROMOSOME_I 130 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCBCCCCDDB@BDBD>ABBADAABBBBA?>ADB>=AAABC>>C AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.24353773 16 CHROMOSOME_I 130 0 7M7I86M * 0 0 TAATCCTGCTTAGTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA @@@9@<>>=>1BBB>?@B>A>?B;AB@>>B<;<>>?7?C=CCC907=9728*82*3-3:=<9>@>BA>=+>@############################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:72A27 NM:i:1 +SRR065390.9158702 0 CHROMOSOME_I 131 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCDBAAD@C@@=>BBCBBDB>ABBBDABDAADBB?D############################################# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:55A44 NM:i:1 +SRR065390.27452830 0 CHROMOSOME_I 131 1 100M * 0 0 AAGCCTAAGCATAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCC('/(/BBBBBCCCCCCCCCCCCCCCCCCDCCCCCDCDDCCDCBD?DDDBDDBBBDBDABBABB>A:B@;@>3@?@?:;6:@/?688<3:: AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:10C89 NM:i:1 +SRR065390.31152354 0 CHROMOSOME_I 131 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCDDCDCCDDDDDDBABDBBBBBBDBBBBAB>ACA@>.@D1/;>>@<6@##################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:79A20 NM:i:1 +SRR065390.33386269 0 CHROMOSOME_I 131 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCACACCBDCCBCDDCABCABCABBBCB;>BB??AA;9=8=?>BB?BB4;B;B>B=B@D=CDC@CCCACAD@DAC@CCCCACCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8335531 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ?DBD?=A?A?66A>BB<>B@B@??@>DAABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8716276 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ###########@??8B;D@@BAB>BB@BB>BB@>@;@CBCC@C?@ACCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12206123 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #####################################@:BAA?AC@@A:5<@53;97>DACCDBDCCCBC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13431089 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ###############@3??A?:B@=>ABDBBDCBBDABADBBBCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14308521 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT 35880;A6AA?DAA@A=AACBC;CAADBBBBDDA@BBBDBACBBCDCBDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17911869 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ####################################ACCAA38C>@C>@ABCCCCCCCCDCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26803411 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ############AA@@31BDB?>@B@A?>8B@BBD;BBBBB>B@@BBACBCCA@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29004521 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ###################A>??=?BBD>BBADCABBBD?DABBBDBADDCACDDACBCCCCCCCCACCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32891184 16 CHROMOSOME_I 133 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #########@@:@@?A;?@??@@@BBBBC?@@@BB>>BCCACC=A==;00000.0000/0+00@=A@################################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:73C26 NM:i:1 +SRR065390.19147644 16 CHROMOSOME_I 134 1 100M * 0 0 CCTAAGCCCACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ####################?>?@BB0B?<@B=@BDDBABCCBCDCCDBACDCDACCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:8T1A89 NM:i:2 +SRR065390.24348183 16 CHROMOSOME_I 134 1 100M * 0 0 CCAACGCCTAGGCCTGAGCCTAACCCTAGGCCTAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #################################################################AA@AAAAA?AAA:?A@7@2@:@A@:>>B9>A0?A0 AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T1A5A4A7G4A9T61 NM:i:7 +SRR065390.26237014 16 CHROMOSOME_I 134 1 100M * 0 0 CCGAAGCCGAAGCCCAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###################################?CA8B@CCC=BCCCC?DCCCCCCCBCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBDCCC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T5T5T5T79 NM:i:4 +SRR065390.26715609 16 CHROMOSOME_I 134 1 100M * 0 0 CCCACGCCTAAGCCCAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #########################@4/>BB@A?BBC@B@B@CD@ACCCCCCCCCCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T1A9T8G76 NM:i:4 +SRR065390.29763377 16 CHROMOSOME_I 134 1 100M * 0 0 CCTGAGCGTAAGCCTACGCCTATGCCTAAGCCTAAGCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA ###################################################################?A9?A?BB>><>;AAAAA>>;><>8>8>??B?: AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3A3C8A5A17A59 NM:i:5 +SRR065390.5592165 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCBCCADCCCCBABDD@DAB=DABB@@@B5>@==B>=B:=>9>A@?><(@/8<8@6:96 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5867686 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCACCCCCCCDCCC@;CCCCCABCACC>DDBBBBB?BADAB>BBB>C;?>>?>B8;??5;@.;>8@## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10729660 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBD>B@BCCCCCBCADCB?BABBBB:;B@BB>BADBBC;BBB:B0?@??B>CB>>A>BAA6=>? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12631494 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCBCC@CC?@BB@CDAABBABAA1?>A?=AA=A;9@?A@*?/B# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14201144 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCC@C;C>ACC?C=CCCB6BCCB5BA@@C##################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16211946 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCADCCCCCDDBBCCABA@CDBDB5DBBD@279;9B>@=@B@@?<@@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16765976 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCBACBCABCD@ABB>AD<=<:87?<=?98=8?########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16773580 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAATCCTAACACTAAGCCTAAACATAAGCCTCAACGTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6BABB<@3>?=1==;D?6D########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28919583 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCACCCCCCCAACBAB@=BBBBB=B@B8:<@=D??;?7@8<19=992@6@################# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.33072912 0 CHROMOSOME_I 135 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCACCCCC@BBABAADBD@<6B?3?A@A::<:9 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4862525 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCDBADCCD@BBDBBDDDDD>A>==?;?BB??B::995>.@@@############ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5774599 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCBDDBBD@@ADBBD@BAABB?D>;?B?>D?D:A2?6=79;9 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13990332 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCACCCCADCDBCCBABACCBBBBABBB??C?;B97;=3>=>>=5-;37=<8=< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17419760 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCACDCCAABCDDD@?B@C@BDDBB>>ACBB6DB########################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.21031614 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBCCDCADCDBBB>DBAB?:BB?@?>BB>@3DABB?ACAC>????D@########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29523788 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCADBDBBBCD@CA@BBBABBDABBDBABABBA############### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29752320 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCDCCCCCCCCDCCDCDDCDCBBBDBB>ABDBB@ABABBBD;AACBAAAAACCAABAAACC@@:;9@############## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.32757960 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCDCCABABBCA@CCB@@BDD@@B@BBB@BBB>B@;@B8@87B;;;>5@<@?=62A##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1606697 16 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###############BBBB>?4@?BABCB>CC8B@BAACCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8349937 16 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG =43?@B6>:???:D?B>B>D?BBB?DABDDBBADCD;CBBCDACABCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9584086 16 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #######################??>A?AA>=9=5>A>AA>AA1@>@D@>6B??:?>:?B>??>?B:@?>BBBBBBDD>8?AA??>8@BB>=ABCDDACC@CCABCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15429543 16 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ######################A=:B6ACAAB?CACABBCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16332923 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCDCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCC?CCCC?CCCCCCCCCA@?BCCBA@@CB=?:5B>BCCACCAC@CCCCCCCCCCCBCBCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19757045 0 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCC@?CCCAAACCCCA;>?>?>CA@BA>AA<<BBD>@D@CADCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23337581 16 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #############################################?7<1:8?CCCCCBCCCCCCBCCCAAA??::<<<<<< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25202138 16 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###############A@>::>BBB>@@?BB@>@=BDAA@DCCCB@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28056173 16 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #########@@8'55<@3=@A:?=BADDBCDDDADCDCACCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28190925 16 CHROMOSOME_I 136 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #########################@8???30235=*??@CBBB>;CC@CA@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13943605 0 CHROMOSOME_I 139 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAGACT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCACCCCC9@BB>A87=>@?################################# AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:85C11C2 NM:i:2 +SRR065390.323629 16 CHROMOSOME_I 139 1 100M * 0 0 GCCTAAGCCTAAGCAGAAGCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##########################ABBA@@@==0===A8@?>>@@;CC=@@7@C8C8CCCC@CCAC>@C=C>CCABBCCCACCCCCBACCCCCCCCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:14C0T7A76 NM:i:3 +SRR065390.14693556 16 CHROMOSOME_I 139 1 100M * 0 0 GCCAGCCCCGACGCCTCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##############################A=@:;==AA===7=>?BBCCC@@CACCDC@DCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3T0A0A0G2T1A4A83 NM:i:7 +SRR065390.30350798 16 CHROMOSOME_I 139 0 100M * 0 0 CCCTACTGCTCCGCCCATCCCTACTCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #########################A@=;:=@?:=:>CC@<;@CCBA5DCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-22 XS:i:-22 XN:i:0 XM:i:11 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0G4A0G0C2A0A3T1A0G4A0G75 NM:i:11 +SRR065390.4780763 0 CHROMOSOME_I 140 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTA CCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCDCCDCCBCCBDBADC@BB;CC@=A;CA>=@BACB>@ABB@A>AAB#################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:95G4 NM:i:1 +SRR065390.10506396 0 CHROMOSOME_I 140 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCA CCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCCCDCAA9ABB@1C@@@A@@A.B@A==(77;73:?6==/@6>@##### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:35G64 NM:i:1 +SRR065390.17927737 0 CHROMOSOME_I 140 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTA CCCCCCCCCCCACCCCCCCBCCCCCCCCCACC?CCCCCACCBB@BBDAABA?B=?########## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92T7 NM:i:1 +SRR065390.27209146 0 CHROMOSOME_I 140 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA CCACBCBCBC@@@AA,CCCCCCC=CCC?CCCCCCCCCCCCCB@CBC>9=8.;=:=789.177042357??################## AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:54C45 NM:i:1 +SRR065390.8223160 0 CHROMOSOME_I 142 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCAAAGCCTAAGCCCAAGCCAAAGCCAAAGCCTAAACCTAAGCCGAAG CCCCCCCCBCCCCCCCC?CCB>BB::??3?ABA>B>ABAAB@B@B@BBB################################################### AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:54T11T5T5T8G8T3 NM:i:6 +SRR065390.28374598 0 CHROMOSOME_I 142 0 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGACAAAGCATACGCGACAGCCCAAGACAAACCACATG <9;;;=A?=>CCACACCCACCCCCCCBCCC=ACAC=CCCBAC@A@?@.>@################################################## AS:i:-30 XS:i:-30 XN:i:0 XM:i:15 XO:i:0 XG:i:0 YT:Z:UU MD:Z:56A7C1T4C2A2C0T0A4T3C1T2G1C0T1A1 NM:i:15 +SRR065390.2772417 16 CHROMOSOME_I 142 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ;7/77:0=1>=7==7@@BBB?4@BBB>DBB@CBDCDDC@DCCACABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5292931 16 CHROMOSOME_I 142 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###############@>9471*=886:?DB>:DB@AAC>BBDB>@DBDDBBDBDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5356550 16 CHROMOSOME_I 142 1 100M * 0 0 TAAGCCTAAGCCTGAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG #####################################?=AC@AA@CC=D@BB?B@@DADD@BDDD@?DC@CDBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12004249 16 CHROMOSOME_I 142 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ##########@*?:@??>B?B;ABBA;BADB=A@BDDAABBDD?DABADCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17100183 16 CHROMOSOME_I 142 1 100M * 0 0 TACGCCTAAGCCCACGCGTAGGCCTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###########################################BA00*0+=C=7@>8C@ACCC5@@CACC@AAC@C>ACC@?;>@;ACA?CC?CA=ABAB AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2A9T1A2C2A4A74 NM:i:6 +SRR065390.19067238 16 CHROMOSOME_I 142 1 100M * 0 0 CAACCCCACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ##########################BD;CB>BBCCB@B@AC0@BABCBCCCCCCCCCCC?CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0T2G2T1A91 NM:i:4 +SRR065390.30164492 16 CHROMOSOME_I 142 1 100M * 0 0 GAACCCCAAGCGTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ##################################B>;<>:=B@?>B>CBCDC@CCDCDDCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0T2G2T4C88 NM:i:4 +SRR065390.30379033 16 CHROMOSOME_I 142 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###################################A>BABBBDB@?DCADBACCCBBCC?DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31408372 16 CHROMOSOME_I 142 1 100M * 0 0 TAAGCCTAAGCCTGAGCCTAAGGCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ##########################################BBB=?BC@@A=@C=C@BC@>C:C@ACCCCCC?@CCCC?CCCCCCCCA@CCCABBCCBC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:13A8C77 NM:i:2 +SRR065390.24902099 0 CHROMOSOME_I 144 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCDC>BDBBA@;CAB>ABB>A?B=:2:=:7=(77@@:<>@=@?# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.26130664 0 CHROMOSOME_I 144 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBDDBDBDBB=ABABB>BB@AA0=A=???@<<>@3@@=+>A7(==7@>8:=(;7749>3@3@######### AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:67C32 NM:i:1 +SRR065390.10040702 16 CHROMOSOME_I 145 1 100M * 0 0 CCCTAAGCCTGAGCCTACGCCTAAGCCTATGCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #################################################################B;BAAABBBBA??AA?@CACCCCC@CCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:4A7G87 NM:i:2 +SRR065390.76906 0 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACC?CCABCCCC0BBAB@.@?BB?:=?1?########### AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:87A12 NM:i:1 +SRR065390.22155458 0 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCA@BCBDDDD@DBBD>@A?AAB0AB>??########################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.407652 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA =944;@<9>7:?@=?9@@B4B@B@ABADBDCDAABCCACCCCC>ACCCCCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.688364 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ?>>?>@D>6@?:=:=7@7>==@A??;22;0B@=;B?BA@@DBDA@@C@C@DBCCCCBACCDBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2431093 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA A>@>A==94=:7A8@?=B4?@=@B?@B@=BDBCBCCBCDCCBA=CACCCCDC;ACCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5178538 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ############################@?>2=8>>@?@B6BDBADBBB@ADAACDCDCCCCCDCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5776200 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #################?@>>ACBAACB>BB>BB>BD?A@@DDDDDCBDCCCCCBDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6963092 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ###############?=??B@?BDD?B:>@BBB>@BBBBD@DBAD@BDDBBBCCDCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7246095 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ################@?A@?;A;?>;BBBB;?@?@@B@@BACBBBBBCBBCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11988452 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ######A>=BC1BBBDD>BABB=BBC@B?AACCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12087571 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ########################BAA4ABBBBBB>6B?@?@=>>)69:===?<=B?=8@## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:83C16 NM:i:1 +SRR065390.12944530 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##########@B@?>:?@????@A@@B@@AA@B@@BCB@@CCACCAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16589531 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ############?A0@ABBDCBB@BBCBDDDDCDCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18782999 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##############################B9B??AB6BBBBBCBBDDBBBBBDDDDBDCCDCDDBCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20251224 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##########################@<3?>?>BADA>BDDBDABADDBBDADCABCCCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22643473 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################@@9??DD>>?>ABB?;BBB?6;BDDAAB@D?BADBDCCBCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCACCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25014137 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ??@???BABB=A>BAB>@BBBBCBBBDDADBBDDDDBDDCBDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31537660 16 CHROMOSOME_I 147 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ############A=9;C>BBD>A;BADDAA@CCCD=CCCCCCACACCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4975670 0 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDCCBCCCCABBCDBBBADBDBBABBAA=B1<@=A=@>B>DB?########## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.10980220 0 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCDCDDBD@B;B?=@############################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.16205013 0 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCBCCCCCCCA?CCCCC>C9?CC@?CCC?6CB7>9/6ACA@@0@;@= AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:88C11 NM:i:1 +SRR065390.19247267 0 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCAAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDCCDCBABCDDA################################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:90T9 NM:i:1 +SRR065390.27744200 0 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACG CCCACCCCCCCCCCC?CCCCCACCCCA@CCBCC?BBBCB>BD>BA@C@?@44A=9=76:?>><><=>=?########################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.48058 16 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###########@=<<>9:6:;AB>>>===:.9>>:>ABDD;BA@DDA2:<<::06=:A:=>B6B@BBB>B@>>@@@?CCB@DCDCCDCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3911401 0 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCC<@CCB=CA@CBCCB;CB@BB@CAABA>?0?><=@9:?/57.3B:B6;:;4B########### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93G6 NM:i:1 +SRR065390.11019398 16 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ###########################A@=?BBC?CCCA@ACCAAB@CC9CC?CC?CCCCCACCCCCCCCCCCCCCCCCCBCCCCDCCCCCDCCDCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17181327 16 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ##########A@@@@A@BC?CBDBBBBADDBBBBAB?>B>?CB@DACDC>D?@>;B@=BBABC>ACDD?6D######################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.30860653 16 CHROMOSOME_I 148 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG ############################@@B?>BA;?A=B8C<=@ACCAB58=8<> AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.428236 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CC@CCCCCCACCCC@C@CCCC8ACCCB>@@CC4CBC>A66??@?8>=78@>,@< AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4115644 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCBCCCCDC@ACCBCBBCCBDAACCACBBBDB=BBABC>>?BBB;@=BBB>>8A=>0A:A=AA>A################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8373173 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCBCCCCCC@CCCCCCCC@B?CDAACCCACCDBBBB;B@C;8BB@A@0D45>737=>=+>@9A?########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9273601 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCBDCCDDADBDDB@AB>BBBB9@@@@8=::877519=8=99?:>A# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9667751 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCACCCDCC@@C@BA@@C??8=<;@@:94==759=>=A############################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10356164 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCBC=>C@DCABBBBBAD?BBB1B><:7.7>A>:5=@=?@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10582969 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=>=>>>@CCCCACCCBBBADDCACBBDBA>DABBABBABB<>B>BDB:>BCA=AA??AA?##### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11554773 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCDC?CDCCCCCBCCBB@BBBBDBD3774;33005=A############# AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.11799834 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCD@BCDDD@BDDDB@ABBBC>D?B@C>8CCA>:A?AD?####### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.12271991 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCBDBABDCDACDC@BBA@A@BBB?>AA>>BD???6@::= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13100135 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCA@CCACC@CAC@@=;8><8B??A?=@=<>:==?;AA=@@B?AAC>5A#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.13252530 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@ADCCD@BDCBB;ADD=B@DBBB@;@@?@=2=?################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14011507 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCC;CCACA8CC@CC@AC@C@?AC8A8=B?5?:DB?;B=@AA?@@.B8=<@=>@@:;?900;10>17> AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14302244 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCDCCDCCCCCCCCBCCCCC@BCCC>@CCACCCCCCCCC=CCC@AACBC=B@@A8:>=B@@?8B=@B;=:>:?BB<@B;>B>BA>A?;:==.>.5555966@= AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15822909 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCC@DAAB;C@=BBAB==BB@;@@BB@@4887=:0>9:@###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.16263688 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBCCDDD@CCDDBADDBB;>BAABB9B###################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18384187 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@DCDBC@BBBBC;BBB>A>DB@=B3@?@>B6>>:9=0;=2::<> AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18577103 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCBCCDCCBBDDADBBB>>DBCCA>AC?AC?AAAA################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19188617 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCBCDBCDBB=B@>AB?6>=2>A>>?;6D?;B@??AA>:AAAAA6<@6@ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.19522689 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCACCCDCDDBDDD@@ABBDB>;BBBBBBCAB>:>>?@9:@@?@96:<@@########################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22784325 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?BCCD@CDCDD@BBABBC8@@AAC@?BBBBBB;>C?@3=@@?=<6=9>83@=@D###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23133897 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCBB:?BA9AA################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23202943 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBCACDCDDDDDD>BADB@ABBBCABB>AB>=>=@@A??AAAA>A################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.25064051 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCBCCCCCCCCCCCCCCCCCC@CCCCCCCCCCDACDCDDABBCB?A@<@ABB@BBD?@AAB>0BB:<=8>A.>:>>/==;AB@::=@########## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29443750 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDABCCBDDB=B@@BB@B>BBB>B?DDA@?ADB:>D?DD<9;-@############ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.29935780 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAACCC@CCCCCCCDCDADDDDDBDCBDDBAABBBABB>B;AABAAAAD################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1999503 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ####################B>@>=4BB@BBB;AADB@BDBBA8CCD@C=DCCCDABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.2979717 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #####################@3@A:?@;=D;???A@;BADBB@BB=?B=CDC@D@CC?@CCCCCCCCCCCCCCCCCCCCCBCCCCCBCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3631589 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCBCCCDBAC@A.=BBBA@?@@BB>?@=@@7?@?A############ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3971739 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ########B:=/5=7:>;4>@=?:7;===2B@BBBBB=BBB5BBBC?@DCCCCCDCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4002088 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@DDCBCABCDCCBACBDB@;BBBBB>?=B@@>@>@<;@############################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4609375 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #########A:3>59@?:=@<=>==6BB@?ACAABA@A@BB;BABBCDDBBDC@DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5221796 16 CHROMOSOME_I 149 1 100M * 0 0 AATACTAGACCTAGGCGTAAGCCTAAGCCTACGCCTAAGCCTAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #############################################################C1CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-16 XS:i:-16 XN:i:0 XM:i:8 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2G0C3A0G4A2C14A12G55 NM:i:8 +SRR065390.5504153 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCDDBDBD>@ADB;=B7A>>=A>BA>>A>@?CAA;ACA6C?@>B<<@<=>?>?;:B?D<9.7@/B74@########### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6311425 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #######@9@@::A::;<.?@BB>8A>BDBBBBDDB=DBDBBADABDDACDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6572328 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCC6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@ACCACCADCBCBDDAAD>BBBAD@@DB4=3===BBB;CC>AA=CAAAA AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6809356 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCACDBCACBDBABBBACCBB;BBBB@;??D@B>AAAAB>@>>?############## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7213562 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ###############BB:>DAABC=ADBBB?A?BBB8?B@>B@DCADDDDDDCCBDBBCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17029406 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC @9'8@:6:,B>9==;6?@:BABBABBBBDAABBDBDAADDDBBDDBCCBCDDCACCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.17428924 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #A9>AA68=>981==A@>??AA==::@AA0@;B@@B;ABAB=B=CBBAB;CC@AB@CDCCCCCCCCCCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18015619 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC?CCCCC@CCCCAACCDB=C@DBB@DBDD6A?=>?>ABBBCBBBABBABDDBDBBBBDDCDCCADCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.20608417 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCABCBBCADBBA>BABBBB>B>>BBBDB@?BA6><=><=D<>B?############################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.31976147 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCATAAGACTAAGCCTAAGACTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ####################################A==A=A8:>@@@BB?C??CA@@CCC@BBC>AA=?BACCCCCCCCCC@BCCCAACCCACCCCCCC AS:i:-11 XS:i:-11 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:4C4C11C34G43 NM:i:4 +SRR065390.33177643 16 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ########@@@A66A@@@=:B;B@@;BBBB@?DBDA@BBDCAAACCCCDACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.33572049 0 CHROMOSOME_I 149 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ?>?B@8;88?>>B9>B@97>@>>980000.*0000838?8:;56722/-/;734@BA4?############################################# AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:93T0A3C0T0 NM:i:4 +SRR065390.824436 16 CHROMOSOME_I 151 0 9M3I88M * 0 0 AATTAAAACAGATAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG B;?8B?BBBD6:5:>3=BBBCBABBBC8@CC@ABACCAC;?CCCCCCCCCCCCCCCCCACCCCCBCCCCCCCCCCCCCCCBCCCCCCDCCCCC AS:i:-38 XS:i:-38 XN:i:0 XM:i:5 XO:i:1 XG:i:3 YT:Z:UU MD:Z:0G0C0C3G0C89 NM:i:8 +SRR065390.8852076 16 CHROMOSOME_I 151 1 100M * 0 0 GCCTAACCCGAAGCCTGAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #####################################C@B8C;?CCCCCCC?CCCCB?CCCCBC?CCCCCCA=>CCBACCCACCCCCBA AS:i:-11 XS:i:-11 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0G3A0A5A38C49 NM:i:5 +SRR065390.24657688 16 CHROMOSOME_I 151 1 100M * 0 0 GCGTAAGGCTACCCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ########################################@4;A?@@+CAAB@=CCC?CDACCCC@?CCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2C4C3A0G87 NM:i:4 +SRR065390.32343734 16 CHROMOSOME_I 151 1 100M * 0 0 GCCTACGCCCACGCCTAAGCCAACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ####################################?BCB=BDBA@DACCCCC@DCCCC==@?(@############################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80T19 NM:i:1 +SRR065390.11017273 0 CHROMOSOME_I 152 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAGCCTA CCCCDCCCCCCBCCCCCABCCCCCCCCCCCCCCBCCBCBCCCCCCCCACCBC?ACC=:=?########################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:90C8A0 NM:i:2 +SRR065390.23405592 16 CHROMOSOME_I 153 0 4M5I91M * 0 0 CGAAAATTTTCGAAAACCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAG @??B?B@BAB<:@BBABABB@@CCCCCDCCCD@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-44 XS:i:-44 XN:i:0 XM:i:5 XO:i:1 XG:i:5 YT:Z:UU MD:Z:1T2G1C0T2G84 NM:i:10 +SRR065390.30873804 16 CHROMOSOME_I 153 1 100M * 0 0 CCAACCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA #####################?:A@6==97B?DDBABBDB?AB@@<>;B>B?DB?=@@?@: AS:i:-8 XS:i:-8 XN:i:0 XM:i:0 XO:i:1 XG:i:1 YT:Z:UU MD:Z:5^T95 NM:i:1 +SRR065390.19270079 0 CHROMOSOME_I 155 6 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTGAGCCTCAGCCTAAGA CCCCCCCCCCCCCCCCCCCCCCCCC@CCBCCCABDCCDCBADBAAB=BBBBB6B@B>ADDDB>.?################################### AS:i:-8 XS:i:-10 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:79A4A5A8C0 NM:i:4 +SRR065390.30567090 0 CHROMOSOME_I 155 6 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTACGCCTCAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCDDCCDCDDDCADBDDDDBBBBBB;CCACAABA>D?##################################### AS:i:-6 XS:i:-12 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:79A11A4A3 NM:i:3 +SRR065390.7022394 16 CHROMOSOME_I 155 0 100M * 0 0 ACGGCTTCGCCTACGCCTATGCCTCAGCCCAACCCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #############################################DCBBBCCCCC=BCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCC AS:i:-20 XS:i:-20 XN:i:0 XM:i:10 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1A1C2A0A5A5A4A4T2G5G61 NM:i:10 +SRR065390.17996680 16 CHROMOSOME_I 155 1 100M * 0 0 AACCCCAACCCGAATCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ######################################?A0.00/0000.;8<5:C?C>CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2G2T2G2T2G85 NM:i:5 +SRR065390.21693823 16 CHROMOSOME_I 155 1 100M * 0 0 ACGCCCAACCCTAAGCCTCAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ##################################@=B0>@<@7?A@CCCCCC@@C@@CC@CCCCCC@C@BCCCBCCCCCCBACCCCCCCB@@??==BB@= AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:1A3T2G9A81 NM:i:4 +SRR065390.27653002 16 CHROMOSOME_I 155 0 100M * 0 0 GAACCAAAACCCAAGCCGAAACCCAAACCTGAGCCCAAGCCCAAGCCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ################################################?<8BA??C?ACACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCBC AS:i:-26 XS:i:-26 XN:i:0 XM:i:13 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0A1G2T2G2T5T2G2T2G3A4T5T5T52 NM:i:13 +SRR065390.31159665 16 CHROMOSOME_I 155 0 100M * 0 0 GAACCGCTCTTCCGATCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #####################################BBCA9>5=BCC@@ACBCCC@@CCC@CCCCCCBCB?@B?@CBCCBCCBCBCCBC?;<><>??@? AS:i:-26 XS:i:-26 XN:i:0 XM:i:13 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0A1G2T0A0A0G0C0C0T0A0A0G0C84 NM:i:13 +SRR065390.11329514 0 CHROMOSOME_I 156 1 100M * 0 0 AGCATAAGCATAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCA CCCCCCCCCCCCCCCCCCCCCBA0==?:?BB>=D############### AS:i:-12 XS:i:-12 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3C5C89C0 NM:i:3 +SRR065390.29072565 16 CHROMOSOME_I 156 1 100M * 0 0 AGCCCAGGCGTAAGCCTACGCCTAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC #######################################################C@.B>@CCCD=CCCCCCCCCA@?<>AACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0G10A88 NM:i:2 +SRR065390.31653691 16 CHROMOSOME_I 157 1 100M * 0 0 CCCCAAGCCCAAGCCGAAGCCGAAGCCGAAGCCTAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #######################################################??5AACCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-14 XS:i:-14 XN:i:0 XM:i:7 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0G2T5T5T5T5T11T60 NM:i:7 +SRR065390.24940664 0 CHROMOSOME_I 158 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCACCCBA@DBDBBBA=??><; AS:i:-16 XS:i:-16 XN:i:0 XM:i:8 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T5T0A4T2G2T5T5T67 NM:i:8 +SRR065390.10545162 0 CHROMOSOME_I 159 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCA CBCCBCCCCCB=??BBBBBBBBBBBBBB:BBBAA@34*2/;?>>>BBBA?882)';8748>B9>B+131@############################## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.12800438 0 CHROMOSOME_I 159 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD@CBBAABDDDBDA*AAA?>>BD@AB+40395=21>*2(22/@@+@<55@## AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:74A25 NM:i:1 +SRR065390.21037219 0 CHROMOSOME_I 159 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCDCA@@>B@@@A>@=@?@?A@05/85;0;8@############### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:99A0 NM:i:1 +SRR065390.27810825 0 CHROMOSOME_I 159 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCTAAGCCTAAGCCTAA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBCD<>CBDDBDADBCDDDBCCCCCCDCCCCCCCCCCCCCCCCCCCCCCCCCCCACCC AS:i:-20 XS:i:-20 XN:i:0 XM:i:10 XO:i:0 XG:i:0 YT:Z:UU MD:Z:3A16A0A0G0C4G2T1A6G2T56 NM:i:10 +SRR065390.8173376 0 CHROMOSOME_I 160 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAG CCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCBDCCD@BDDDBB=A@@??8BB;D9?DD;BAAAA=AA### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98A1 NM:i:1 +SRR065390.24971098 0 CHROMOSOME_I 160 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAG CCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCBBCCCCCCACDCA@@AAC6BABB=D@>@B>?>@1==377.5055(52049467 AS:i:-3 XS:i:-3 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:97A2 NM:i:1 +SRR065390.29229469 0 CHROMOSOME_I 160 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCCTAAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCACCCCCCCBB?CCCABCA@C:=B@BC?=B==@==?@@A################# AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:90T9 NM:i:1 +SRR065390.15931715 0 CHROMOSOME_I 162 1 100M * 0 0 NGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC !++++22222AAA8AAAAAAAAAAAAAAAAAAAAA8:0:8AAAAAAAAAAAAAAA78AA7:89996664:AAA########################### AS:i:-1 XS:i:-1 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0A99 NM:i:1 +SRR065390.16420564 0 CHROMOSOME_I 163 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCCCCCCC@CBC>@AA:A>?CA?@AB=A=@BBA@BADB=BBABCCAAA)A AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23326095 0 CHROMOSOME_I 163 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCACCBBABAB>DBBB=>B@@?B?B>BB6BBD<>4?==@@A@9@=7AB;B;BAD;@DACD=DCDDCC?CCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4460513 16 CHROMOSOME_I 163 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ####################BD@:BBBABABBABDABDDDC=CCCDCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4608863 16 CHROMOSOME_I 163 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT A;A2::::=.@.<@@=A>BDDADCCBCB@CCCCBCCCDCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.10096102 16 CHROMOSOME_I 163 1 100M * 0 0 GCCGAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT #########################@3;B@79;99>=BBA?@A;@=>>D::99=4=@*:BB>AB@@@BDDBDDDDCDACACCCCCACCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.27063479 16 CHROMOSOME_I 163 1 100M * 0 0 GCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCT ##########################################@BB@B;ACA@B=CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4604929 0 CHROMOSOME_I 164 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBDCDDDDBDDDBD@DDA?B>?*:B8@@8=@??A?>B?A## AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:81A18 NM:i:1 +SRR065390.21767995 0 CHROMOSOME_I 164 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCTAAGCCTAAGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC>D@AA@=?@####################################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:75A24 NM:i:1 +SRR065390.24370235 0 CHROMOSOME_I 164 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCCA CCCC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCCCCCD=A>DBB@;@BBB;=?=6A:=A################################ AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92T5T1 NM:i:2 +SRR065390.33289921 0 CHROMOSOME_I 164 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCTA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCAACBBCCCC@BCCB>B@@B@B9B?B?:0>==D?:>?############### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:88A11 NM:i:1 +SRR065390.33450079 0 CHROMOSOME_I 164 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@CDBCCDDDB@DBDDBBA?B@>@BABB6>=>>94@<==@#################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92T5T1 NM:i:2 +SRR065390.9104074 16 CHROMOSOME_I 164 1 100M * 0 0 CCTAAGCCTAGGCCTAAGCCTAAGGCTAAGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #################################?777?:5@B=B?B?;BDB@ABBA18BBACCCC####################################################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:96T1A1 NM:i:2 +SRR065390.6217548 0 CHROMOSOME_I 166 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAGG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCADDCACB?@@?@B@BBD=:=;7ABAAB@:?BD############################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:96T1A1 NM:i:2 +SRR065390.22416659 0 CHROMOSOME_I 166 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGACTAAGCCTAAGCACAAGCGTAAGCCTAAGCCTAAG ?A=8?@AA@?CCCCCBBBBB:8:?:78307>@#################################################################### AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:64C12C0T4C16 NM:i:4 +SRR065390.29369023 0 CHROMOSOME_I 166 1 100M * 0 0 TAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTCAG CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDBBDDCBBDBDDBDBCABA>BCACC>CAAAAA?A?>:=CA@9;787;8A48;8@######################## AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:86G1C11 NM:i:2 +SRR065390.19225398 0 CHROMOSOME_I 167 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGCCTAAGCCCAAACCCAAGC ?<:<<>AA@>CCCCCB@B@=58;;?<>@BA>B@BB<@B9BBBBBBA>@############################################## AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:79A9T2G2T4 NM:i:4 +SRR065390.21123303 0 CHROMOSOME_I 167 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGACTCAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC######################################################## AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:72A2C2A21 NM:i:3 +SRR065390.29022479 0 CHROMOSOME_I 167 0 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTAAGCCTAATCCTATGCATAAACCTAAACAGAATCAAAAGAAAAATCCAATCT CCCCCCCCCACCCCCBCCCC?CCCCCCCD;?D?D################################ AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:94C0T0A3 NM:i:3 +SRR065390.23298396 16 CHROMOSOME_I 167 1 100M * 0 0 AAGCCTCGGCCTACGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC #####################A@><>B==BC@CCBB?BA'@>>;>>DADDDBDBADB?B6@7=;;7DBD?B<8=AA:4-9<@@1:@A################################ AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:98C1 NM:i:1 +SRR065390.23263331 0 CHROMOSOME_I 168 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCBCCCDCCDCDDDBBDA=B@BB@B>B>AB?@?BB>;;ACC>CAA@;9<5@############## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.1428659 16 CHROMOSOME_I 168 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC #######?DB@;>BBB::>:D=>D?BDDBBBBCCAC@DCCBDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9270489 16 CHROMOSOME_I 168 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ##########?4=>@BAA>BB>AA@====3BBBBB;B?@C==CCC?@CCC?CCC?ACCCCCBCCCBCCCCBCCCCCCCCCCCCCC=BCCCCCACCCDCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.9538669 16 CHROMOSOME_I 168 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ##########@=?6??@B;BA@@@?.@?@@;D>A;DB@DBBBD>@DDDBADCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.15525407 16 CHROMOSOME_I 168 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ####################@37:0BC@@C@ACCAB?@CCACCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18387934 16 CHROMOSOME_I 168 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ##########################@@A@4BDDBB@ACABB@8BCACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.27778447 16 CHROMOSOME_I 168 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCC ###############@@B=;>89<>/8?<8@>=ABDCCDCC@CCACB@@C@9ACCCC;CCCC@CCAAB@@CCCCCBCCCCCCCBCCCCCCCCCCCCCCCC AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.4767844 0 CHROMOSOME_I 170 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTAAGCCTAACCCCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCCDCC=CCBA=BCCACCBCC<@@@A@>A?D<5/772AA####################### AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80T14G2T1 NM:i:3 +SRR065390.6036148 0 CHROMOSOME_I 170 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCTCAGACCA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCBCCC=C########################################## AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:86T6A2C1T1 NM:i:4 +SRR065390.7523697 0 CHROMOSOME_I 170 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTATACCTATGCATA 8773399<;8BBB>BAA<A################################### AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:84C3A4A5A0 NM:i:4 +SRR065390.21777229 0 CHROMOSOME_I 170 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCCAAGCCCAAGACCAAGCCAAGACCCC CCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCCCCCCCCCCCCCBDABAA@48@############################################# AS:i:-18 XS:i:-18 XN:i:0 XM:i:9 XO:i:0 XG:i:0 YT:Z:UU MD:Z:74T5T3C1T5T1A0G2T0A0 NM:i:9 +SRR065390.22082412 0 CHROMOSOME_I 170 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTTGGCCGCAGCCTCAGCCTGAACAGA CCCCACACCCCCCCC??:??@CCCC@9A>9?AA@AC>@CA@B-73>8=53@=:=A?><=>49778?################ AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:88A5A5 NM:i:2 +SRR065390.32243033 0 CHROMOSOME_I 170 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTACGACTA CCCCCCCCCCCACC@CCACCCCCCCCCCCCCCCCC@CADCCBBD@BB>=?A@9C@?C>A88?>8A?:@CCCCCCCCC:?>;:CCC?BCCCCACCCCCCCCCC AS:i:-39 XS:i:-39 XN:i:0 XM:i:18 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0C0T0A0A2C0T2G1C0T0A0A0G0C1T0A1G1C64C10 NM:i:18 +SRR065390.28296401 16 CHROMOSOME_I 171 1 100M * 0 0 CTAAGCCTAAGCCTAAGGCTAAGCCTAAACCCACGCCTAGGCCGAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA ##################################################BAADDDBBDDCCDCCCCCACDCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-12 XS:i:-12 XN:i:0 XM:i:6 XO:i:0 XG:i:0 YT:Z:UU MD:Z:17C10G2T1A5A3T56 NM:i:6 +SRR065390.1242089 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC A=@@?=?=8A3BB>>B@B>BAB@B@B77//8<;>5:@@@B6ABA@BA<@BB5):5;*83736?;;;@@=;6B>??##################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.3872193 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCBCCCC@DCACD=ABCB@BCDDA@BA=BBB@C??@;:0A>?>B>?)?#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.14566073 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCBCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCAB=?CCCA6?AACABCCAC=1B@A@;B<@A@@;>?@>8BB?B#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18391952 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCDCCCAADCCB?CBABD=A>?BB5:??:B;>?@AA?>3?;@(8>=>>/(5500;+@@6 AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.18719419 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCAC@@C@@B@DBBDBB################################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23668023 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCC@@ABDB@@BBB>DBABB@D@BDBAABAB>B>AA@??9:8>>A:255@###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.23826980 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCDCDBCDDBDDDABBBBDDBBBBBBB>D?#################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.28024258 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCBACDDBC>DDBDB>BBBBB;?@BBB3@???=0<=>@@:@################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.30039772 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCDACDBBDDDDDBBBDBBD>BBAADAABAAC??B??######################### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.5345749 16 CHROMOSOME_I 173 1 100M * 0 0 GACCCAGACCCCGCGCCTAAGCCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ##########################################@BA=>AAA@;AAAA@AA9AAAA@BAA@:=@@@4A=?A@AAAAA:B@@BBBBB@>>>>> AS:i:-18 XS:i:-18 XN:i:0 XM:i:9 XO:i:0 XG:i:0 YT:Z:UU MD:Z:0A1G2T0A1G2T0A0A9T76 NM:i:9 +SRR065390.16932911 16 CHROMOSOME_I 173 1 100M * 0 0 AACCCTAAACCTAACCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC ###############B?BAA;;9>0A1BAAA@=CA*@CCCCACCCC@@?CAAB>AC=C?CCCCBCCBBCBCCCABCCBCA@CCCCCCBCCCCC?BCCCCC AS:i:-6 XS:i:-6 XN:i:0 XM:i:3 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2G5G5G85 NM:i:3 +SRR065390.17106354 0 CHROMOSOME_I 173 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCACC?CCADCCAC@BB@CBB@C?@A@@A>=B?BAABBABB6A>BBB:BBA=?DD??;D/<71; AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.22716808 0 CHROMOSOME_I 174 1 100M * 0 0 AGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCGAAGCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCABBBBB?################################### AS:i:-2 XS:i:-2 XN:i:0 XM:i:1 XO:i:0 XG:i:0 YT:Z:UU MD:Z:94T5 NM:i:1 +SRR065390.12986460 0 CHROMOSOME_I 176 1 100M * 0 0 CCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCATAATCGTAAGACTAAGAGCAAGCCTCAGCATA CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA?CCA############################### AS:i:-4 XS:i:-4 XN:i:0 XM:i:2 XO:i:0 XG:i:0 YT:Z:UU MD:Z:92T2G4 NM:i:2 +SRR065390.14729559 16 CHROMOSOME_I 176 1 100M * 0 0 CCTACGCCCAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTA #########################?(4<=B@;BBBBCB?>BCCA?DCCACCCCCC@C;BBB??B<;9=C@BCAACBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC AS:i:-8 XS:i:-8 XN:i:0 XM:i:4 XO:i:0 XG:i:0 YT:Z:UU MD:Z:2T0A0A6G88 NM:i:4 +SRR065390.26023345 0 CHROMOSOME_I 177 1 100M * 0 0 CTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTCAGCCGAA CCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCA?CDADABDBDDBDDBAB>>BBBB@;>@BBB?A>CBBB<>>B@@4@?>>?0ABD@@###### AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6149508 0 CHROMOSOME_I 179 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCDDCCBD=CCDB@@DABAB=ABB??>>@BB=BCBAB>>D;A?><>AA>?A==+@A AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.6618950 0 CHROMOSOME_I 179 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCDCCCCCDCCBCAACBBCBB@DADABBDAB?CBB@B;?BB=B>>>?:? AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.7246333 0 CHROMOSOME_I 179 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCACCCDCCCCCCCCCCCDCCBCD@CBBDCADADADBDABBDBDABDBCBBA>BAB>>AC9A################## AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 +SRR065390.8266146 0 CHROMOSOME_I 179 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAACCCTCAGCCGAGGCCTACGC CDCCCCCCCCCCCCCCCCCBCCCCCCDCCCCCCACDCCCCCDACBDCABCB@A=ABBB@BBD@DB?B################################# AS:i:-10 XS:i:-10 XN:i:0 XM:i:5 XO:i:0 XG:i:0 YT:Z:UU MD:Z:80G3A4T1A5A2 NM:i:5 +SRR065390.8986893 0 CHROMOSOME_I 179 1 100M * 0 0 AAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGC CCCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCCCCCCA@CCCCD=CCCDAABBDB>BDDBDB;BB@@B=@BDB:.A>>BB:@################ AS:i:0 XS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 YT:Z:UU MD:Z:100 NM:i:0 diff --git a/src/test/resources/htsjdk/samtools/cram/md#1.2.1.cram b/src/test/resources/htsjdk/samtools/cram/md#1.2.1.cram new file mode 100644 index 0000000000..159e8340c5 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/cram/md#1.2.1.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/md#1.3.0.cram b/src/test/resources/htsjdk/samtools/cram/md#1.3.0.cram new file mode 100644 index 0000000000..e9cd1710ac Binary files /dev/null and b/src/test/resources/htsjdk/samtools/cram/md#1.3.0.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/md#1.sam b/src/test/resources/htsjdk/samtools/cram/md#1.sam new file mode 100644 index 0000000000..7e2c0c0726 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/md#1.sam @@ -0,0 +1,12 @@ +@HD VN:1.0 SO:coordinate +@SQ SN:a LN:40 +x 0 a 1 255 40M * 0 0 AAAAAAAAAACCCCCCCCYNNRGGGGGGGGTTTTTTTTTT * NM:i:2 MD:Z:19N0N19 +x* 0 a 1 255 40M * 0 0 CAAAAAAAANNCCCCCCCYNNRGGGGGGGGTTTTTTTTTC * NM:i:6 MD:Z:0A8A0C8N0N18T0 +xIP 0 a 1 255 1I10M1I10M2I10M2P3I2P10M1I * 0 0 NAAAAAAAAAAGCCCCCCCCCCAAGGGGGGGGGGCCCTTTTTTTTTTN * NM:i:12 MD:Z:18Y0N0N0R18 +xIP* 0 a 1 255 1I10M1I10M2I10M2P3I2P10M1I * 0 0 NCAAAAAAAAAGCCCCCCCCCCAAGGGGGGGGGACCCATTTTTTTTCN * NM:i:16 MD:Z:0A17Y0N0N0R7G0T8T0 +xD 0 a 1 255 9M1D8M2D7M3D6M * 0 0 AAAAAAAAACCCCCCYNNRGGGGGTTTTTT * NM:i:9 MD:Z:9^A6C0C0^YN0N6^GGG6 +xD* 0 a 1 255 9M1D8M2D7M3D6M * 0 0 CAAAAAAANNCCCCCCTTGGGGGGTTTTTA * NM:i:13 MD:Z:0A7A0^A0C6C0^YN0N0R5^GGG5T0 +xN 0 a 1 255 10M20N10M * 0 0 AAAAAAAAAATTTTTTTTTT * NM:i:0 MD:Z:20 +xN* 0 a 1 255 10M20N10M * 0 0 CAAAAAAACCAATTTTTTTA * NM:i:6 MD:Z:0A7A0A0T0T7T0 +xS 0 a 11 255 5H10S20M10S5H * 0 0 AAAAAAAAAACCCCCCCCYNNRGGGGGGGGTTTTTTTTTT * NM:i:2 MD:Z:9N0N9 +xS* 0 a 11 255 5H10S20M10S5H * 0 0 CAAAATAAAACCCCCCCCYNNRGGGGGGGGTTTTATTTTC * NM:i:2 MD:Z:9N0N9 diff --git a/src/test/resources/htsjdk/samtools/cram/md.fa b/src/test/resources/htsjdk/samtools/cram/md.fa new file mode 100644 index 0000000000..3723483e17 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/md.fa @@ -0,0 +1,3 @@ +>a +AAAAAAAAAACCCCCCCCYNNRGGGGGGGGTTTTTTTTTT + diff --git a/src/test/resources/htsjdk/samtools/cram/md.fa.fai b/src/test/resources/htsjdk/samtools/cram/md.fa.fai new file mode 100644 index 0000000000..87f55859d4 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/md.fa.fai @@ -0,0 +1 @@ +a 40 3 40 41 diff --git a/src/test/resources/htsjdk/samtools/cram/xx#repeated.2.1.cram b/src/test/resources/htsjdk/samtools/cram/xx#repeated.2.1.cram new file mode 100644 index 0000000000..cb04d56083 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/cram/xx#repeated.2.1.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/xx#repeated.3.0.cram b/src/test/resources/htsjdk/samtools/cram/xx#repeated.3.0.cram new file mode 100644 index 0000000000..18c38ffebc Binary files /dev/null and b/src/test/resources/htsjdk/samtools/cram/xx#repeated.3.0.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/xx#repeated.sam b/src/test/resources/htsjdk/samtools/cram/xx#repeated.sam new file mode 100644 index 0000000000..88fc3d6b4b --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/xx#repeated.sam @@ -0,0 +1,7 @@ +@SQ SN:xx LN:20 +S 67 xx 1 1 10M = 11 20 AAAAAAAAAA ********** +S 131 xx 11 1 10M = 1 -20 TTTTTTTTTT ********** +S 67 xx 1 1 10M = 11 20 AAAAAAAAAA ********** +S 131 xx 11 1 10M = 1 -20 TTTTTTTTTT ********** +S 67 xx 1 1 10M = 11 20 AAAAAAAAAA ********** +S 131 xx 11 1 10M = 1 -20 TTTTTTTTTT ********** diff --git a/src/test/resources/htsjdk/samtools/cram/xx#tlen.2.1.cram b/src/test/resources/htsjdk/samtools/cram/xx#tlen.2.1.cram index ecf339678a..2de38f8f3d 100644 Binary files a/src/test/resources/htsjdk/samtools/cram/xx#tlen.2.1.cram and b/src/test/resources/htsjdk/samtools/cram/xx#tlen.2.1.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/xx#tlen.3.0.cram b/src/test/resources/htsjdk/samtools/cram/xx#tlen.3.0.cram index ec1b380ebe..b5dc1ee47d 100644 Binary files a/src/test/resources/htsjdk/samtools/cram/xx#tlen.3.0.cram and b/src/test/resources/htsjdk/samtools/cram/xx#tlen.3.0.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/xx#tlen.sam b/src/test/resources/htsjdk/samtools/cram/xx#tlen.sam new file mode 100644 index 0000000000..4b2f70eb8d --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/xx#tlen.sam @@ -0,0 +1,34 @@ +@CO xx has been encoded using the SAM spec; leftmost to rightmost +@CO yy has been encoded using bwa/picard methods; 5' to 3' +@CO +@CO 00000000011111111112 +@CO 12345678901234567890 +@CO AAAAAAAAAATTTTTTTTTT +@CO 1>>>> <<<<2 x1 +@CO +@CO 1>>>> x2 +@CO <<<<2 +@CO +@CO 1>>>> x3 (7..15 vs 10..11) +@CO <<<<2 +@CO +@CO <<<<2 1>>>> x4 (1..20 vs 16..5) +@CO +@SQ SN:xx LN:20 +@SQ SN:yy LN:20 +x1 99 xx 1 1 5M = 16 20 AAAAA ***** +x1 147 xx 16 1 5M = 1 -20 TTTTT ***** +x2 99 xx 7 1 5M = 10 8 AAAAT ***** +x2 147 xx 10 1 5M = 7 -8 ATTTT ***** +x3 147 xx 7 1 5M = 10 8 AAAAT ***** +x3 99 xx 10 1 5M = 7 -8 ATTTT ***** +x4 147 xx 1 1 5M = 16 20 AAAAA ***** +x4 99 xx 16 1 5M = 1 -20 TTTTT ***** +y1 99 yy 1 1 5M = 16 20 AAAAA ***** +y1 147 yy 16 1 5M = 1 -20 TTTTT ***** +y2 99 yy 7 1 5M = 10 8 AAAAT ***** +y2 147 yy 10 1 5M = 7 -8 ATTTT ***** +y3 147 yy 7 1 5M = 10 -2 AAAAT ***** +y3 99 yy 10 1 5M = 7 2 ATTTT ***** +y4 147 yy 1 1 5M = 16 10 AAAAA ***** +y4 99 yy 16 1 5M = 1 -10 TTTTT ***** diff --git a/src/test/resources/htsjdk/samtools/cram/xx#tlen2.2.1.cram b/src/test/resources/htsjdk/samtools/cram/xx#tlen2.2.1.cram index 558e4dd9bb..5700fa7cea 100644 Binary files a/src/test/resources/htsjdk/samtools/cram/xx#tlen2.2.1.cram and b/src/test/resources/htsjdk/samtools/cram/xx#tlen2.2.1.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/xx#tlen2.3.0.cram b/src/test/resources/htsjdk/samtools/cram/xx#tlen2.3.0.cram index add9c38421..bccc3400ee 100644 Binary files a/src/test/resources/htsjdk/samtools/cram/xx#tlen2.3.0.cram and b/src/test/resources/htsjdk/samtools/cram/xx#tlen2.3.0.cram differ diff --git a/src/test/resources/htsjdk/samtools/cram/xx#tlen2.sam b/src/test/resources/htsjdk/samtools/cram/xx#tlen2.sam new file mode 100644 index 0000000000..b02989ea1e --- /dev/null +++ b/src/test/resources/htsjdk/samtools/cram/xx#tlen2.sam @@ -0,0 +1,36 @@ +@CO As per xx#tlen.sam but every read is unsorted with partner +@CO +@CO xx has been encoded using the SAM spec; leftmost to rightmost +@CO yy has been encoded using bwa/picard methods; 5' to 3' +@CO +@CO 00000000011111111112 +@CO 12345678901234567890 +@CO AAAAAAAAAATTTTTTTTTT +@CO 1>>>> <<<<2 x1 +@CO +@CO 1>>>> x2 +@CO <<<<2 +@CO +@CO 1>>>> x3 (7..15 vs 10..11) +@CO <<<<2 +@CO +@CO <<<<2 1>>>> x4 (1..20 vs 16..5) +@CO +@SQ SN:xx LN:20 +@SQ SN:yy LN:20 +x1 147 xx 16 1 5M = 1 -20 TTTTT ***** +x1 99 xx 1 1 5M = 16 20 AAAAA ***** +x2 147 xx 10 1 5M = 7 -8 ATTTT ***** +x2 99 xx 7 1 5M = 10 8 AAAAT ***** +x3 99 xx 10 1 5M = 7 -8 ATTTT ***** +x3 147 xx 7 1 5M = 10 8 AAAAT ***** +x4 99 xx 16 1 5M = 1 -20 TTTTT ***** +x4 147 xx 1 1 5M = 16 20 AAAAA ***** +y1 147 yy 16 1 5M = 1 -20 TTTTT ***** +y1 99 yy 1 1 5M = 16 20 AAAAA ***** +y2 147 yy 10 1 5M = 7 -8 ATTTT ***** +y2 99 yy 7 1 5M = 10 8 AAAAT ***** +y3 99 yy 10 1 5M = 7 2 ATTTT ***** +y3 147 yy 7 1 5M = 10 -2 AAAAT ***** +y4 99 yy 16 1 5M = 1 -10 TTTTT ***** +y4 147 yy 1 1 5M = 16 10 AAAAA ***** diff --git a/src/test/resources/htsjdk/samtools/example.bam b/src/test/resources/htsjdk/samtools/example.bam new file mode 100644 index 0000000000..18b96c15cc Binary files /dev/null and b/src/test/resources/htsjdk/samtools/example.bam differ diff --git a/src/test/resources/htsjdk/samtools/inttest_large_coordinates.bam b/src/test/resources/htsjdk/samtools/inttest_large_coordinates.bam new file mode 100644 index 0000000000..b88e777337 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/inttest_large_coordinates.bam differ diff --git a/src/test/resources/htsjdk/samtools/inttest_large_coordinates.sam b/src/test/resources/htsjdk/samtools/inttest_large_coordinates.sam new file mode 100644 index 0000000000..2329990515 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/inttest_large_coordinates.sam @@ -0,0 +1,26 @@ +@HD VN:1.5 SO:unsorted +@SQ SN:Sheila LN:1000000020 +@RG ID:ID SM:foo +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P0:i:0 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P1:i:127 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P2:i:128 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P3:i:255 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P4:i:256 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P5:i:32767 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P6:i:32768 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P7:i:65535 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P8:i:65536 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P9:i:2147483647 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** PA:i:2147483648 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** PB:i:4294967295 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P0:i:-0 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P1:i:-127 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P2:i:-128 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P3:i:-255 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P4:i:-256 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P5:i:-32767 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P6:i:-32768 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P7:i:-65535 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P8:i:-65536 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** P9:i:-2147483647 +Fred 16 Sheila 1000000001 86 10M * 0 0 GCTAGCTCAG ********** PA:i:-2147483648 diff --git a/src/test/resources/htsjdk/samtools/io/dictionary_english_short.dic b/src/test/resources/htsjdk/samtools/io/dictionary_english_short.dic new file mode 100644 index 0000000000..0916263a75 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/io/dictionary_english_short.dic @@ -0,0 +1,4563 @@ +A +Abietineae +Acanthurus +Achromobacter +Acropora +Addison +Adullam +Aetomorphae +Agelacrinites +Ahmadabad +Akontae +Albizzia +Alemannic +Alhambresque +Almira +Altica +Ambocoelia +Ammiaceae +Amphisile +Anamnia +Andalusia +Angers +Anisoptera +Anselmian +Anthropopithecus +Aonian +Apluda +Aptiana +Arara +Arcos +Argonaut +Arlene +Arthrodira +Asclepius +Aspidoganoidei +Asuri +Atractaspis +Aurantium +Avernal +Azteca +Bacillarieae +Bakersfield +Balnibarbi +Bannock +Barotse +Basuto +Bdelloura +Belialic +Bennet +Bernardina +Betty +Bilin +Blackstone +Bodo +Bombus +Borromean +Bourignonist +Brahminic +Brevirostrines +Brontosaurus +Bube +Bulgaric +Bute +Caca +Cairo +Callianassa +Calyptratae +Campbellism +Cantabrigian +Caracas +Caridomorpha +Carpophaga +Cassytha +Catonic +Celastrus +Cephalacanthidae +Cercospora +Chaenomeles +Chamaesiphonaceous +Chartres +Cheney +Chimakuan +Chloe +Christdom +Chrysidella +Cicuta +Cixiidae +Clematis +Cnidoscolus +Coelebogyne +Collybia +Comptometer +Conopidae +Coraciiformes +Coropo +Coueism +Crimean +Cryptodira +Cummins +Cyathophyllum +Cynodon +Cytherea +Dailamite +Danite +Dasyatidae +Decemberish +Demeter +Derotrema +Dianthus +Dicynodontia +Dinornis +Diprotodontia +Dode +Donnelly +Doxantha +Dschubba +Dutch +Ecaudata +Eden +Einstein +Eleutheria +Ely +Enchytraeidae +Entamoeba +Epicurism +Eretrian +Erythraea +Eteoclus +Euglandina +Eurindic +Evan +FPC +Farmington +Ferae +Filipiniana +Flamandize +Forestiera +Frankify +Freya +Funariaceae +Gaertnerian +Galli +Ganodus +Gaulle +Genesiac +Gerbillus +Geullah +Gino +Glomerella +Godiva +Goode +Gradgrindish +Greenblatt +Grubstreet +Guesdist +Gyges +Hackett +Halcyoninae +Hamitoid +Harold +Haversian +Heiltsuk +Hellenize +Henry +Herniaria +Heteromeri +Hibernicize +Hippidion +Hittite +Holomyaria +Honshu +Hubbard +Hussite +Hydrodictyon +Hypnos +Iapygian +Idaic +Illyrian +Indologue +Ionization +Isabelline +Israelite +Itylus +Jacunda +Japanophile +Jennifer +Jim +Jorgenson +Juglans +Jutlander +Kalwar +Kashmirian +Kenai +Khattish +Kirby +Knoxian +Koppers +Kruger +Kyrie +Laguerre +Lancelot +Laridae +Lauraceae +Leighton +Leonine +Leptophis +Leucothoe +Ligurian +Linet +Lithuanian +Lodowick +Lophiidae +Loyolite +Lula +Lychnic +MIT +Macrocentrus +Maenalus +Maiidae +Malebolge +Manchurian +Maorilander +Marguerite +Marsilia +Mastigopoda +Maybird +McDowell +Mediterraneanism +Meistersinger +Mellivora +Mentha +Merula +Metaurus +Micraster +Milesian +Minoress +Mithraistic +Mohammedanization +Monachi +Mononchus +Montpelier +Morrenian +Mru +Murzim +Mycosphaerella +Mystacocete +Nabalitic +Naomi +Navajo +Negroize +Neogene +Nesokia +Nice +Nipissing +Nordicize +Notogaeic +Nyctaginaceae +Ochozoma +Ods +Oleacina +Onchidiidae +Opimian +Origenical +Orthocarpus +Osphromenidae +Ottawa +Oyana +Pakawan +Palestinian +Pandean +Paphian +Parinarium +Pasquino +Paulinistically +Pedimana +Peltandra +Perameles +Perognathus +Petrarchist +Phalangida +Phegopteris +Philotria +Phronimidae +Physoderma +Picuris +Pipil +Placoides +Platyhelminthes +Pliosauridae +Podophthalmata +Polonia +Polyporaceae +Populist +Powell +Prionodesmacea +Prosobranchiata +Protosphargis +Psittacidae +Ptilota +Purdue +Pyrodine +Quakerishly +RCA +Ramistical +Rastaban +Reki +Rhamnales +Rhodian +Richfield +Roccella +Romescot +Roth +Rumford +Rymandra +Sabine +Sahadeva +Salol +Samsonian +Saoshyant +Sarigue +Saurodontidae +Scaphitidae +Schneiderian +Sclerodermatales +Scotsmen +Seasan +Seljukian +Septembrist +Serrano +Shakespeareana +Shemu +Shoshonean +Sifatite +Simonist +Siphonata +Siwash +Smectymnuan +Sokulk +Sopherim +Spaniardo +Sphaeriidae +Spioniformia +Squatinoidei +Steatornis +Steve +Strickland +Stylops +Suliote +Svetambara +Sylviinae +TV +Tagliacozzian +Tamias +Tapijulapane +Tartarized +Tchetchentsish +Teleostomi +Terebridae +Tetrodon +Thamudic +Theresa +Thoracostei +Tibetan +Tinoceras +Tocharic +Toromona +Trachymedusae +Tribulus +Trinucleus +Trochodendraceae +Tubificidae +Turbinellidae +Tursha +Tyrannosaurus +Ugrian +Uniat +Uropeltidae +Valencia +Variolaria +Veneres +Vespertiliones +Virgil +Voss +Wahl +Wapato +Webb +Westminster +Wiley +Witumki +Xanthidium +Xiphura +Yankeeland +Yoruban +Zamenis +Zenobia +Zolaistic +Zygophyllaceae +abacas +abastardize +abdias +aberdevine +abietic +ablastemic +abnormals +aborigine's +abrasions +abscise +absoluteness +abstentions +abterminal +abysmally +acanthine +acatastasia +acceptance +accidently +accommodations +accountableness +accultural +accustoms +acescents +acetomorphine +acetylization +achloropsia +acicularly +aciliated +acocotl +acquaintance +acraze +acrocephalous +acronically +acrylonitrile +actinometers +activin +aculeolus +ad-nauseum +adat +addlehead +adenase +adenoneure +adherescent +adipopexis +adjunct +administer +admittedly +adonis +adpress +adsorption +aduncity +adverbiation +advisor's +aegean +aerie +aerogen +aerophilatelic +aesthetic's +affectibility +affirmation's +affraying +aforetime +afterfame +afterrake +afwillite +agateware +ager +aggravations +agistor +agnations +agoraphobic +agriculture +aguinaldo +aidman +aion +airier +airspeeds +ajowans +alabaster +alarmism +albification +albuminuric +alcoholic +alderwoman +alepole +alfaje +algidity +alibied +alike +aliveness +alkane +allassotonic +allemand +alliterate +allogamous +allorrhythmic +allows +alma-mater +alnagership +alp +alright +alternations +altun +alvar +amalgamates +amasty +ambassage +ambitious +ambrotype +ameliorativ +americium +amidate +aminoacetal +amman +ammonolyze +amongst +amp +amphibryous +amphiploidy +amphorette +amputee +amygdalate +amylosynthesis +anacephalaeosis +anaerobically +anagyrine +analphabet +anankes +anarchal +anathematizes +ancestries +ancistroid +androgametangium +anecdotes +anepithymia +angaries +angiocarpic +angiosperm +angolans +anhalamine +anilities +animators +anisogenous +anklejack +annelid +announce +annunciates +anomalonomy +anorexia +anspessade +antasthmatic +anteflexion +antepasts +antetemple +anthoecologist +anthracomancy +anthropolater +anthropophysiography +antiantidote +anticapital +anticlactic +anticourt +antidotes +antifebrile +antigraph +antiking +antimasque +antimoniureted +antioptionist +antiperistatically +antipolygamy +antiquarians +antirevolutionaries +antisilverite +antisubmarine +antitoxin's +antivivisectionist +antrustionship +aorists +apathic +aphakia +aphoria +apicifixed +aplome +apocynaceous +apologias +apoplastogamous +apostolate +appallingly +appellant +appertainment +applicabilities +apposer +apprenticeship +approvedness +apsides +aquarial +arab +araliad +arbitrationist +arbutus +archangel's +archdruid +archfriend +archines +archmagician +archprimate +arctangent +arecas +arfvedsonite +argled +arianist +aristocratism +armamentarium +armored +aromas +arrantly +arrisways +arsenhemol +arsonous +arteriostenosis +arthromere +articulatenesses +artocarpeous +asarum +asceticism +ascyphous +ashless +asmalte +asperous +aspirate +assarion +assenters +asshead +assister +asst +astasia +asthmatoid +astral +astrologian +aswim +atamascos +athalamous +athletocracy +atmocautery +atomizing +atriocoelomic +attacks +attendress +attiring +attritive +audience +augen +auletic +auresca +aurophore +ausu +authoritatively +autobusses +autocrator +autogauge +autoist +automobile's +autoplast +autosite +autotrophic +auxocardia +avenalin +avianize +avitaminosis +avoyer +awearied +awreck +axised +ayegreen +azofier +azoxazole +babbled +baby +bache +backbonelessness +backlands +backslidden +backwardness +bacteriolysis +badge +baga +bagworm +bain +baking +balas +balers +ballate +ballpark's +balsamer +banana +bandit's +banging +bankruptlike +bantering +barbacou +barbicans +barefit +baria +barmaids +baronetcies +barras +barroom +baryte +basest +basihyoid +basketball +bassos +bateaux +bathybic +batster +battleship's +bavoso +bayoneting +beadings +beamster +bearishly +beau's +bebed +becharm +becolor +bed +bedells +bedlamism +bedrivels +bedward +beekeeper +beevish +befogged +begari +beglamour +beguile +behint +bekerchief +beld +belion +bellmaking +belonging +bemata +bemuse +beneceptive +benevolentness +bentwoods +benzoates +benzoxyphenanthrene +beprose +beret +bern +besagne +beshaming +besmile +bespatter +bestayed +bests +bethanking +betrayers +bevel +bewidow +beys +biallyl +bible's +bibliotaphic +bicircular +bicyclists +biethnic +bigamous +bigotish +bilberries +biliverdic +billowiness +bimethyls +binna +biochore +biographic +bionomy +biostatics +bipedality +birched +birdy +birthright's +bishopess +bisters +biti +bitumed +biznagas +blackfellows +blacktail +blamelessly +blankness +blastogranitic +blauwbok +bleaters +blennometritis +blesboks +blindling +blitzbuggy +blockmaking +bloodred +bloop +blowhard +bluebelled +bluer +blunker +boanergism +boatings +bobo +bodewash +bog's +bohea +boldo +bolshevists +bombers +bondmen +bonita +boobyalla +bookland +boomdas +bootful +boraciferous +boreism +borrowable +bosquet +botchery +bottlenecks +bouk +bouquets +bovinely +bowlegs +boxinesses +brabant +brachistochronous +brachyuranic +bradypod +braids +brake +branchiostegous +brashier +brattles +brayera +breadman +bream +brecken +bret +briarberry +bridally +bridlers +brightly +brininesses +britches +broadhorn +brogue +bromeliad +bromopnea +bronchorrhea +brooding +brothels +browpost +brunets +brutalized +bubblies +bucketed +buckwheatlike +buffable +buggered +bulbaceous +bull +bullfoot +bullwort +bummest +bundook +bunnymouth +burdener +burgherdom +burkite +burntness +bursts +bushlands +bust +butene +buttermonger +butylates +bwanas +byrnies +cabaletta +cabinetwork +cache +cacodylic +cactaceous +cadew +caesarian +cagmag +cakemaker +calandria +calcigerous +calculi +calibogus +calix +callosum +calorizer +calycanth +cambaye +cameramen +campanologer +campions +canal +cancellus +candle +caner +cannabinol +cannonproof +canorousness +cantilevering +canvasser +capellet +capitalizes +cappadine +capshore +captivating +caracols +caravels +carbonado +carburate +cardaissin +carding +cardiorenal +careful +carid +carminic +carnotite +carpal +carpolith +carroming +cartilagineous +carvel +cascaron +cashbook +cassavas +castigable +casuistically +catalecta +catamiting +catatonias +catechist +caterer +catheter +catling +cattleman +caulescent +causeless +cavalier +cavil +ceaseless +cee +celestialness +cellblock +cementations +censorious +centerless +centralizations +centrolineal +cephalocele +ceraceous +cercarias +cerebromeningitis +ceriph +certiorate +cervuline +cetolog +chaetopterin +chair +chalcidid +challengers +chamfrons +chancellories +changer +chapah +chaptalize +charcoals +charladies +charter +chasteningly +chattingly +cheapened +checkoff +cheeping +cheetah +chelonin +chemoreceptivities +cherishingly +chetah +chias +chickenwort +chiffonade +chilenite +chimars +chinchy +chippage +chiroplasty +chisellike +chladnite +chlorinators +chlorophyllan +choel +cholecystectomy +cholesteremia +chondritis +chondrule +chordata +chorioids +chorussing +chrismon +chromatolysis +chromocyte +chromotype +chronometrical +chrysolite +chufas +chunters +churner +chymic +ciceros +cilioscleral +cinel +cinnamonic +circuitable +circumaxillary +circumlocution's +circumspectness +cirrocumulus +cited +citrinous +civilizer +claimer +clamp +clapperclaw +clashingly +clastics +clavial +clays +clearwater +clemencies +clerkships +cliffside +clinching +clinopyroxene +clitoridectomies +clockwatching +clomping +clostridial +cloudlets +clubbable +clumsiness +cnicin +coadjutator +coagulometer +coamings +coastings +cobalt +cobstone +coccothraustine +cockatoos +cockneyess +coconut's +codelight +codlings +coeline +coenduring +coercionary +cofeature +cogeneric +cognizers +coherent +coiler +coinsurer +colcothar +colicystopyelitis +collatable +college's +collinearly +colloquium +colometry +colophony +colory +coltsfoot +colytic +combinational +comediennes +comic +comme +commentation +commissary +commonalties +communicates +compactible +compartmental +compendium +complacence +complex +compliments +compotator +comprizes +computerization +concealed +conceptism +conchal +concludable +concreting +condensability +condole +conductus +confecting +confessionals +confirmations +conformate +confutations +conglobe +congresswomen +conjecturalist +conjurement +connexus +conquering +consecution +conservatories +consisting +consortium +constipating +constructionally +consultor +containers +contemptibly +contiguities +continuousness +contractively +contrapone +contravention +controversional +convect +converging +conveyances +convolved +cookery +cooniness +copaibas +copiable +coppersmith +coprophagan +copyholds +coracovertebral +cordelle +coregence +coriparian +cornein +corning +coronach +corporate +correctant +corridored +corrupter +corticous +coryphee +cosinesses +cosmopolitanize +costeaning +costumiers +cotingoid +cottontop +couldst +countdown +counteravouchment +countercurrent +counterfeited +counterlatration +counterpassion +counterquarterly +counterside +counterterrors +counting +courap +courtyards +covenantor +cowages +cowleech +coxcombicality +cozily +cracklier +cragginess +cranelike +crankcase +crapulousness +cravenhearted +crea +creational +creditor's +creirgist +creolism +cressed +crewing +crimeproof +cringed +crispened +critiqued +croft +crooner +crosscurrented +crossways +crow +crucial +cruller +cruors +crutch +crypta +cryptolog +crystallogenical +cubanite +cubododecahedral +cudgelers +culex +culprits +culverts +cumulated +cupay +cuproiodargyrite +curatorship +curiae +curmurring +cursive +curvatures +cushiony +customizers +cutization +cwierc +cyanol +cycads +cyclohexyl +cycloses +cylindromatous +cynanthropy +cyprian +cysticolous +cystospasm +cytolytic +czaritzas +dacryoadenitis +dactylus +dagga +daincha +dalk +damme +damselfish +danegeld +daphnioid +darkeys +dartoic +datableness +daubster +dawdlingly +dayman +deaconize +deadwood +dean's +deathrate's +debauchees +debriefings +decadrachma +decants +decatyl +decenary +dechlorinate +decipherability +declarers +decoic +decongestant +decoying +decrypted +dedication +deemphasizes +deface +defecter +deferentitis +defines +deflorations +deforms +degasify +degraduation +dehumidifying +deintellectualization +delabialize +delete +delightingly +deliver +deluders +demarcation +demiatheism +demilance +demisangue +democratical +demonised +demoralizing +denationalize +deniable +denotationally +dentatocillitate +dentosurgical +deoperculate +depas +depicting +deplump +depositor's +depressible +deputatively +deregulation +dermal +dermatorrhagia +dernier +desaurin +desecrate +desexualization +desilvers +desmohemoblast +desperacy +despumate +destructions +detainable +determinably +detinet +detruncation +deutonymph +developmentally +deviltries +devotee's +deweylite +dextrogyrous +dhooly +diacetylene +diagnoses +dialed +dialyzate +dianoetical +diapophysis +diastoles +diazoanhydride +dicast +dichromatic +dictator +didder +diem +diffeomorphic +diffused +digged +dignitarial +diiodo +dilatometer +dilutent +dimidiate +dimyaric +dinitrophenol +dioestrum +dioxy +diplasiasmus +diplomatists +diprotodont +directiveness +dirtplate +disaffirmative +disappointed +disassociation +disbuds +discerpibility +disclosed +discommender +discontentment +discouragement +discretions +disdainfully +disemploy +disenthralled +disfranchisements +disgustful +dishonesties +disincarnation +disinterestednesses +dislimning +dismemberments +disoperculate +dispassioned +dispersement +displode +disprivilege +disquietedness +disrobers +disseizing +dissettlement +dissociative +distale +distills +distrain +disturbance's +dita +dittied +divergently +dividedly +divisural +djebels +docimology +doctrinarily +dodecasyllable +dogdoms +doglegs +doitrified +doll +doltishness +domineer +donenesses +dool +doorweed +dormin +dorsocaudal +dosses +doubledamn +doughboys +doven +downcoming +downrightly +dowse +drabness +dragging +draine +drapers +drawknot +dreamfully +dreidls +driftage +drisk +dromedarian +dropper's +drownded +druith +drusy +dubash +duckfoot +duds +duikers +dulse +dumper +dungier +duodenocholedochotomy +duplicating +durion +dustlessness +dwayberry +dynametrical +dysacousis +dysmorphism +dystrophy +earlike +earthier +easel +ebb +eccentrate +echea +eclamptic +economy's +ectocondylar +ectozoa +edema +edifier +educatory +effacers +effigial +eflagelliferous +eglateres +eider +eisodic +elaborative +elastomeric +electable +electroanalysis +electrodynamic +electrolyzable +electrophoric +electrotest +elegit +eleutherophyllous +eliminant +elmier +eluants +elytrocele +emasculating +embays +embleming +embosture +embroilment +embuia +emetically +emmenagogue +empanels +emplaces +emptive +emyd +enanthem +encarpus +encephalotome +encl +encoronet +encup +endearing +endoblast +endoenteritis +endophasic +endosmometer +endowers +energies +enflagellation +engarment +englut +engrossingly +enisling +enlightener +ennobled +enquiries +enrut +ensilages +ensued +enter +enteromycosis +enthrallment +entocnemial +entophytically +entrapping +enumeration +environmental +enzymotic +epanorthotic +ephebos +epibranchial +epicoracoid +epidermophytosis +epigonic +epimanikia +epiphytic +episcotister +epistolizable +epitheliomatous +epizoicide +epyllion +equianchorate +equimolar +equisetic +eradiate +eremitish +ergostat +erminee +errancies +eruditeness +erythrocytorrhexis +escalin +escheats +eskers +espaliered +essaying +esteem +estivator +esugarization +ethanols +ethide +ethnographically +ethynyls +eucalypti +eudaimonia +eulogist +euphemian +eupnoeic +eutaxic +evaluative +evaporite +eventuated +evictees +evocatively +exact +examinationism +excandescence +exceptiveness +excitements +excommunicant +exculpatory +executant +exempted +exhalents +exhorter +existing +exogenetic +exorcisory +exotoxins +expecters +expenditures +expiations +explications +exponentially +expounds +expungers +exsuccous +extenuatory +extine +extracapsular +extraessentially +extraperiodic +extraterrestrials +extrication +exultingly +eyeglasses +eyewinker +facade +facings +factotum +faeces +faineants +fairyology +falcopern +falsettist +familistical +fanfares +fantast +farced +farls +farsightedly +fascistization +fastuousness +fatigable +fauces +favaginous +fayles +featherback +febricant +federated +feels +felinity +feloniously +femininity +fendillate +ferfathmur +fernleaf +ferrocerium +fertilizer +festooning +fettered +feverous +fibration +fibrofatty +fice +fiddlesticks +fieldish +fiftieths +figurize +filename's +fillable +filmy +finalis +finfish +finises +firearmed +firelocks +firmed +fishery +fissility +fitch +fixature +flaccidity +flagonet +flamelet +flanky +flashier +flattening +flavid +flea +fleeciest +fleshpots +flickery +flinting +flittern +flockmaster +floorless +florida +flotative +flowerpecker +flugelman +flung +fluoridize +flushness +fluxility +flyting +fod +fogram +folia +folksong +fondnesses +fools +footloose +foozlers +forbearingness +fordless +forecar +foredevised +foreguidance +forelay +forepassed +forescript +forespeed +foretelling +forfairn +forgiver +formagen +formers +formulize +fort's +fortuitus +fossilation +foulish +fourgons +foxed +fractionalized +fraik +frangipane +fraternally +freaked +freeing +freight +frescoed +fri +friendliness +frill's +frithbot +frocklike +frondeur +frosh +frowners +fruit +frustrates +fuddled +fuguing +fullface +fumaryl +functionality +fungible +funnily +furfurole +furores +fusc +fustians +fuzz +gable +gaels +gainlier +galactorrhea +galera +gallet +gallon's +galvanist +gambe +gamesmanship +gammy +ganglia +ganoid +garage +gardy +garnet +garrotting +gasiform +gasterosteoid +gastroduodenoscopy +gastropancreatic +gat +gaudiness +gauzewing +gayish +gearings +geisha +gelees +gemmier +genealogic +generations +geniculum +genro +gentlest +geodaesia +geologian +geophones +geoty +germanization +gerontophilia +gesticulation +gharry +ghostliest +gibbetting +gifts +gigmanic +giltcup +gingering +gipons +girns +gizzern +gladiatorism +glamouring +glasshouse +glazing +glenlike +gliosa +globigerine +glomerulose +glossarize +glossopodium +glub +glummest +glycan +glycolysis +gnarr +gnetaceous +goalposts +gobiiform +godlier +goglet +goldfishes +gombos +gongman +gonophs +goodwilly +gooseherd +gorgeted +gosmore +gouged +governmentish +grabouche +gradometer +grains +gramophonical +grandma +grannom +grape's +graphs +grasswards +grave +gravitationally +greases +greenbone +greenthumbed +gressorial +grievous +grimier +gripper +grittiness +groomers +grotesquely +groundworks +growlers +gruelers +grumpish +guam +guarder +gudefather +guffaw +guilefully +gulches +gumboil +gundi +gunrooms +gurniad +gutsier +guydom +gymnogenous +gynecologists +gypsophily +gyrons +hability +hackbolt +hadjis +haffit +hagiarchy +hairband +hairtail +halcyons +halisteresis +halluces +haltere +hamiform +hampshirite +handcuffing +handles +handstroke +hangworm +haplodonty +haranguers +hardfern +harebottle +harman +harnessing +harsh +haslet +hatcheling +hatter +hausens +haviours +haycap +hazed +headhunts +headrope +healthier +heartening +heat +heavenly +hecatomb +hedgeberry +heel +heightened +helianthic +heliolatrous +hellbent +helmetmaker +helter-skelter +hematidrosis +hematometry +hemialbumose +hemifacial +hemiparasitic +hemitrope +hemoglobic +hemorrhaging +hencoops +hep +hepatopneumonic +heptarchic +herbariums +hereat +hereticize +hermitess +heroinism +hes +heterization +heteroecism +heterology +heteroproteide +heterozygosis +hexadactylic +hexane +hexiological +hiccuping +hierarchial +higginsite +hightailing +hills +hindsaddle +hippiatric +hippopod +hirsuteness +histogeny +historiographic +hiveward +hobble +hocusses +hoghide +hoking +holiness +holmgang +holomorphy +holts +homeliness +homesickly +hommock +homoeomorphy +homograft +homophobia +homovanillin +honeymooned +honors +hook +hoopstick +hoplonemertine +horizontically +hornsman +horrifies +horseplay +hose's +hostie +hoti +houseboy +houseminder +how +hubb +huffily +hulloes +humblebee +humidifying +humorology +hungered +hurlbarrow +husbanded +hustlers +hyalobasalt +hydatoscopy +hydrazine +hydrocephalies +hydroforming +hydromania +hydrophilid +hydrorachis +hydrotherapy +hygiastic +hylobatic +hymnic +hypapophysial +hyperboles +hypercycle +hyperfunction +hypermetamorphism +hyperoxide +hyperridiculous +hyperthermy +hyphening +hypoacid +hypoconule +hypogea +hyponasty +hypoploidy +hypostomous +hypothyroid +hypsoisotherm +hysterogenous +iatrochemical +icequake +ichthyologies +iconoclasticism +idaho +identifications +idiogenesis +idioticon +idoloclastic +ignifying +ijolite +iliotrochanteric +illimitation +illuminational +illuvium +imbalances +imbosoms +imitativeness +immedicable +imminences +immortalizable +immuration +impanate +impassionate +impedances +imperatorious +imperishability +imperturbed +implacableness +implied +importable +impostress +impredicable +impressiveness +impropriety +impugns +inaccessibilities +inadvisedly +inapplication +inaugur +incalculably +incase +inchoately +inciters +incoalescence +incommunicado +incomprehensiveness +inconsecutiveness +incontrolled +incorrigibly +incrimination +inculture +indamins +indefinable +indentured +indiadem +indifferentistic +indirubin +indistinctiveness +indoctrinates +inducedly +indults +inebrious +inembryonate +inerts +inexpectant +inextricable +infaunas +infernality +infiltrating +inflames +inflows +infrabestial +infrapubian +infuriately +ingestion +ingrowth +inheres +inia +injectable +inkles +inmeshes +innovated +inodorously +inositols +inquisitively +inscenation +insecurely +insheathe +insistently +insouling +inspoken +instigatingly +instructed +insufficient +insurgency +intarsist +intelligence +intensifier +interangular +intercalm +intercitizenship +interconnection +interdependently +interfaith +interfuse +interjacency +interleaver +interlunar +intermessenger +intermuscular +internuncios +interplait +interpreters +interrenalism +interseamed +interstage +intertragian +interventional +interzygapophysial +intitules +intracanonical +intraglobular +intransitives +intratarsal +intrinsicality +introspectionism +intuition's +inures +invasions +invermination +invests +invited +involvements +iodinating +ioniums +irascibleness +iridocele +ironflower +irradiations +irreducibility +irremediableness +irresolutions +irrigating +isallobar +isepiptesis +isoamylene +isochores +isodontous +isohel +isomerize +isopleth +isostemony +isovalerone +italic +itinerant +jabbering +jackets +jaculated +jailbait +jambs +japanizing +jarool +jaundicing +jaypie +jeez +jemmy +jermonal +jetport +jibbah +jillions +jinket +jobbernowlism +jog +joist +jonathan +jouked +jowing +jubilance +judicatories +jugulate +jumbly +jungly +jurels +justifiably +juxtaterrestrial +kagus +kalam +kamaainas +kans +karosses +kashima +kathode +kecking +keepering +kelpie +kenoticist +keratoleukoma +kernel +ketogen +keying +khankah +kibitka +kidnapper +killed +kiloword +kindredness +kingcob +kinkly +kirned +kitcheny +kjeldahlize +klystron +kneecaps +knighthood +knoll's +knowledgement +koeberliniaceous +koller +koppie +kotwalee +kremlins +kubba +kurrajong +kylix +labialize +labors +lacepiece +laciniation +lacrym +lactonize +ladify +laevoduction +laicality +lakeweed +lambies +lamentingly +lampads +lancelike +landladyship +landslips +languishing +lanthana +lapel +lapsing +largen +larsenite +laryngotome +lassoers +lateralis +lathesman +latrias +laughful +laurel's +laves +lawsuit +lays +leaden +leafy +learners +leatherworking +lecithins +leechkin +legaleses +leggings +legitimizes +leisureful +lene +lenticulare +lepidoid +leptocephalid +lessened +letterspace +leucocytosis +leukomas +levigated +lexically +libations +liberia +lice +lichting +lienic +liferenter +lightbrained +lightwort +likelihood +limans +limewort +limnologist +linages +linemen +linguatuloid +linkwork +lioncel +lipochrome +lippiest +liquidy +listen +lites +lithographical +lithotomous +littlenecks +liverheartedness +loaches +loathsomely +lobscouser +locellus +locoed +lodesman +logbooks +logium +loined +loners +longitude +lookdowns +looten +loranthaceous +lors +loudened +lousiness +loverwise +lowth +lubricative +lucking +luggageless +lumberman +lumpier +lungees +lupinine +lushest +luteciums +luxuriated +lymnaean +lymphomas +lyretail +maar +mach +macilency +macroclimate +macromolecules +macrotome +madeiras +maegbote +magi +magnesic +magnetotelephone +maharajrana +maidy +mainour +majestious +malacanthine +malapertness +malcontentedness +malexecution +malinstitution +malnourishment +maltol +mammectomy +manageableness +mandamused +manducate +mangers +manienie +manito +mannitic +manslaughtering +mantuamaker +manuscript +marabouts +marceline +margeline +mariner +markmoot +marooner +marse +martensitic +marvelling +masher +massages +masterer +mastitis +matadors +materialities +matmaker +matronism +maturish +mauther +maximises +maysin +meadowbur +meanie +meatiest +mechanotherapy +median +medicinableness +mediopectoral +meebos +megagametophyte +megameter +megrim +melanger +melassigenic +melismas +melodies +melosa +memo +menagerie +meningococcal +menotyphlic +menthone +mercaptole +mercuriate +meristele +merohedrism +mesalike +meshier +mesocaecum +mesomyodian +mesoscutellum +messages +metabolical +metafulminuric +metallicity +metamerically +metaphorist +metarhyolite +metatitanate +meteorographic +methine +methylpentose +metrical +metrophotography +mezcals +mica +microbars +microclimate +microdose +micrography +micrometrically +microphotography +microscope's +microsublimation +midbrain +midmandibular +midweek +migratations +mildnesses +milk +millenniarism +millimeter +millrace +mimers +minatorially +minerva +miniconventions +minimizers +ministerialness +minorate +minutiose +mirish +misadventures +misappraise +misbegan +miscalling +misclasses +miscookery +misdemeanor +miseducates +misexplication +misgovernment +misinferred +misky +mismanager +misogynism +mispick +mispursuit +misrepute +missioning +misstopped +misthrift +mistrustful +miswords +mitral +mizzentopman +mobil +modal +modernizers +modulations +moiety +molarities +molests +moloid +moments +monarchianism +moner +mongolian +monk's +monobrominated +monoclinally +monody +monographers +monometer +monophthongization +monoptote +monosulphide +monotypes +montanic +mooched +moonless +moorflower +moping +moravia +morg +moroc +morphographical +mortality +mortuary +mossers +mothership +motorable +motto +mounds +mousehawk +mouzouna +moyo +mucket +mucronate +mudless +muggers +mulctatory +mullite +multicultural +multihearth +multinodous +multipolar +multisulcated +multurer +mundanity +muntjaks +murk +muscadels +musculotendinous +musiclike +muskwood +mustermaster +muth +mutualities +mycetoid +mydriasis +myeloneuritis +myocarditic +myoneme +myotics +myristicaceous +mystagogically +mythogenesis +myxoenchondroma +nacarat +naiad +nakedness +nannandrium +naphthanthracene +narcissistically +naringin +nasalization +nassellarian +nationalizing +naturedly +nautics +navvies +neat +necessarily +necrolatry +nectarium +needy +neglective +neighborstained +nenta +neomenian +neothalamus +nephritis +nepote +nervosity +netherworld +neuralist +neurocele +neurologists +neuropsych +neurotrophic +nevi +newsmagazines +nibble +nicknack +nidificational +niggerfish +nightmary +nikethamide +nineteenth +nisse +nitroaniline +nitty-gritty +nobless-oblige +nocuousness +noggins +nombles +nomophylax +nonactionable +nonalcoholic +nonaqueous +nonautomated +nonbusiness +nonchampion +noncollaborative +noncomputation +noncongratulatory +noncontrastable +noncrushable +nondegenerate +nondeterminately +nondisfigurement +noneducation +nonenforcements +nonevanescent +nonextensive +nonfictional +nonfuturity +nonhearer +nonimpregnated +nonintellectually +nonjurorism +nonmalicious +nonmineralogical +nonnescience +nonorthographical +nonpenal +nonplushed +nonprimitive +nonprotractile +nonrecess +nonremembrance +nonresuscitation +nonsale +nonsensify +nonsludging +nonstationary +nonsummons +nonteetotaler +nontribal +nonutterance +nonvitrified +noonday +normalize +northward +nosism +notaeum +notharctid +notorieties +novate +novice +nubbling +nucleolus +nugatoriness +numbingly +nummulite +nursekin +nutmeat +nybbles +o +oat +obeisance +obituary +oblateness +obliterator +obscenely +observatories +obstinative +obtrusive +ocarina +occlusions +oceanographer +ochronosis +octapla +octogenarians +octuplex +oddnesses +odontolcous +odso +oersted +offerable +offlet +ogive +oilfield +okays +olecranon +oliganthous +oligopyrene +oloroso +omentotomy +omnigraph +omnivarious +onanistic +oneiroscopic +onomatologist +ontosophy +oogenesis +oophoromalacia +opacous +opera's +operose +ophthalmite +opiliaceous +opisthognathism +opposite +opsonification +optimisms +opuscules +orant +orbitolite +orchidist +ordinal +orfrays +organogold +orgue +originals +ornateness +ornoite +orpins +orthodiazine +orthonitroaniline +orthostichous +oscella +osculum +osotriazole +ostariophysous +osteoderm +osteophagia +ostracized +otherwhiles +otomassage +oud +outasks +outblot +outbuilds +outclimb +outdispatch +outerwear +outflare +outglared +outhold +outlandishly +outloved +outpasses +outpractice +outran +outroaring +outsells +outsizes +outspoke +outstrive +outthinks +outvoices +outwile +ouzos +oven's +overalled +overbaked +overblows +overbuilds +overchannel +overcomer +overcontribute +overculture +overdepress +overdoses +overeducated +overexercise +overfamed +overflexion +overfunctioning +overgown +overhated +overhung +overinfluencing +overkeenness +overleave +overlove +overmelodied +overnight +overperemptory +overpowering +overprosperous +overreaction +overrighteous +oversaturated +oversentimentally +oversimply +overspacious +oversteps +oversubscribes +overtask +overtip +overtwine +overwears +overworship +ovisac +owerword +oxaluric +oxidates +oxyacids +oxyhaloid +oxyterpene +ozonide +pachalics +pachypodous +packman +padlike +paganish +pahlavi +paintier +palaeichthyic +palaeolithoid +palagonitic +palatorrhaphy +paleocrystal +paleophysiology +palimony +pallet +palmatisect +palosapis +paltriness +pampootee +pancratiastic +panderer +panelist +panickier +pannikin +pansideman +panterer +pantometry +paolo +papermouth +pappescent +parabaptism +parachute +paradisean +paragastrular +parakeratosis +parallelopipedon +parameterizing +paranuclear +paraplectic +parasite's +paratactic +parazonium +pardoners +parergic +parietosplanchnic +parlay +parochine +paroophoritis +parricidism +parsonlike +participant +partitions +parvirostrate +passados +passir +pasteurizer +pastural +patellofemoral +pathfinders +pathos +patricianhood +patron's +patties +pauperize +pavlov +payably +peacemaker +peaking +peasantry +pechs +pectoralgia +pedalier +pedestalled +pedimental +pedunculation +peetweet +pejorative +pellas +pelted +penalising +pendragonship +penicillinic +pennet +penseful +pentadecane +pentangle +penthiophene +peonage +pepperweed +peracids +percepts +percussively +perfecter +perforator +periangitis +pericecitis +peridermal +perigynial +perineal +perionyx +peripherophose +perishables +peristoma +peritrochium +perlaceous +permittivity +peroratory +perplex +persevered +personating +persuadingly +perturbed +perviability +pestiferously +petechiate +petrifier +pets +pewful +phaenogamian +phalangitic +phansigar +pharmaceutic +pharynges +phasers +phengitical +phenotypically +philanthropically +philodemic +philoprogenitive +philters +phlegma +phocoid +phoneticohieroglyphic +phonophotoscope +phosphid +phossy +photocombustion +photogastroscope +photolithography +photophily +photospherically +photovisual +phrenicocostal +phthalide +phylae +phyllophyte +physicalistic +physiognomic +physoclistous +phytology +phytotomist +piazza +pickaway +picktooth +pictogram +piebaldism +pieridine +pigeons +pigpen +pilaws +pilimiction +pilocarpine +pimpernels +pinchbugs +pinfold +pinkest +pinning +pintado +piped +pipper +pirogue +pisiforms +pit's +pithecomorphism +pituitaries +placated +placodont +plagues +plaitwork +planforms +planners +plantule +plasmon +plataleine +platings +platycephalous +plaudite +playlets +pleasance +plebiscitary +plemyrameter +pleonal +pleurite +plexal +plinks +plotty +plucker +plumbing +plumpened +pluralizes +plushy +pneomanometer +pneumoderma +pneumotherapy +poco +podiums +poecilonymy +pogey +pointedly +poker +polars +policewoman +politicizing +pollinating +poltfooted +polyaxone +polyclona +polyfoil +polygraph +polymaths +polynome +polyphagous +polypodiaceous +polysepalous +polysynthesism +polyvinylidene +pomologically +ponderosa +pontificates +poon +poplar +populi +porismatically +porpentine +portass +portionize +pory +possessedly +postamniotic +postclavicular +poster +postformed +postindustrial +postmesenteric +postpathological +postsacral +postumbilical +potatory +potherb +potstick +poulp +pouter +poxvirus +praecornu +pragmatists +pranksome +praya +preachiest +preadministrator +prealcoholic +preapperception +preballoting +prebudgetary +preceded +precessions +precised +precognize +preconcealed +preconfusedly +precontractive +precredit +predazzite +predeliver +predestinationism +predict +prediscontinuation +prediversion +preeminently +prefaced +prefertilization +preformative +pregnancies +prehensorial +preimpressive +preinscription +preissuance +prelawfulness +preludize +prememorandum +premoistened +prenebular +preoccupate +prepackaged +prepersuasive +prepossessingness +prepuces +preregister +prerich +presbyterians +presence's +presetting +presoak +pressurage +prestos +presuperfluity +pretangibly +preterintentional +pretorture +preutilization +preverb +preweigh +pricker +priesting +primero +primp +principle +priorly +privater +proaesthetic +probabilities +problems +proceeding +procivism +proconstitutional +proctocystotomy +procurement's +prodromus +proettes +professionless +profligacy +prognathi +progressism +projections +proletarianization +prologuize +promiscuousnesses +prompters +pronic +propaedeutical +propendent +prophoric +propolises +proprecedent +propylitization +prorsal +prosecutrices +prosodal +prosperation +prostrated +protectant +protensive +prothetical +protocoling +protomala +protopodite +protovillain +protuberantial +proverbiology +provivisectionist +proximo +prurigos +psammocarcinoma +pseudimago +pseudobulbil +pseudodementia +pseudographia +pseudomantist +pseudonymuncule +pseudopupal +pseudostalagmite +psiloceratan +psychanalysis +psychoepilepsy +psychomotility +psychosomatic +pteridium +pterygomalar +pub +pucellas +pudginess +pugging +pulers +pulmonarian +pulsate +pulvination +punched +punditries +punks +pupil +purchase +purin +purporting +pursier +pushier +putchen +putties +pycnosporic +pyla +pyopneumocyst +pyrans +pyriformis +pyrography +pyrophone +pyrrhotist +qere +quadrates +quadrifoliate +quadripolar +quadruplicature +quaked +quanta +quarrelingly +quartic +quatral +queechy +quenchless +questionableness +quickens +quietness +quincuncially +quinolyl +quinquesyllabic +quintroon +quislings +quizzing +quotients +rabbity +racemous +racisms +radiability +radicle +radiography +radiostereoscopy +raffe +ragger +railleries +rainstorms +rallentando +ramicorn +ramped +ranchos +ranging +rantipole +rappelled +rarety +raspings +ratfish +rationalizer +rattlejack +rave +ravishments +razzed +reaccompanies +reactionarism +reading +reafflict +realizingly +reanimated +reappraised +reascend +reassignments +reattraction +rebarbarization +rebestowal +reboundingness +rebunker +recampaign +recash +receptacles +recharged +reciprocations +reclaimant +recoct +recollects +recompenses +reconciliable +reconnaissance +reconsult +recopyright +recrated +recruiting +rectocystotomy +recurs +redate +redeclaration +redelivery +redetention +redirects +redistricting +redowas +reduced +reed +reelected +reenforcement +reestimating +refashioned +referrible +refix +reflexology +reforged +refractionate +refrigerations +refusers +regathering +regimenal +reglazing +regreen +regularly +reharmonization +rehousing +reimbush +reinclude +reinforcers +reinstalls +reintrenched +reitbuck +rejudging +relast +relay +reliable +relime +relocator +remanence +remedies +remindful +remittors +remord +remurmur +renegers +renominates +renumbered +reoperate +repacked +repasted +repent +rephase +repledge +repoint +repot +representor +reproachableness +reprography +republicanization +repurification +requisitionist +rerival +rescaling +resection +resentful +reshaping +resides +resinfiable +resizer +resolvedness +respade +respoke +restaging +restir +restrap +resubmission +resupplying +resyntheses +retardence +rethrash +retimed +retirements +retractively +retreats +retrocession +retrolabyrinthine +retrusible +reunitedly +revanches +revengeless +reversal +revictualed +revisualize +revolubility +rewardableness +rewins +rhabdomes +rhatanies +rheumarthritis +rhinolithic +rhizomorphic +rhodospermin +rhymes +riatas +ribspare +rickettsialpox +ridge's +riffler +righthanded +rikshaws +rinch +ringster +ripening +rishi +rituality +riverwash +roadman +robed +rocheted +rockweed +roentgenologically +rokeage +romanced +romping +roofwise +root +roping +roseine +rosolios +rotatory +rotundifoliate +roughish +roundline +rouths +rowiness +rubbernecking +rubify +rudder's +ruffer +rugs +rumbustical +rumples +runlet +ruralise +russify +rutherfordium +sabadine +sabots +saccharogalactorrhea +sachemship +sacrificature +sadden +saeter +sagamen +saguran +sainted +salamandarin +salicylaldehyde +sall +salpas +salted +salubriously +salviol +samisens +sanctifiableness +sandbanks +sandra +sanguine +sanjaks +saphena +sapped +sarabands +sarcomatoid +sarges +sartor +satchel +satirised +saturdays +saugh +sautoir +savories +sawmills +sayyids +scaffolds +scalewing +scampi +scantling +scapulospinal +scariness +scatomancy +scelidosaur +sceptry +schepen +schizocarpic +schlepped +scholarless +schoolkeeping +schuits +scillain +sciotherically +sclerencephalia +scleroskeleton +scolecid +scooters +scorekeeping +scotogram +scouthering +scraighing +scratchably +scree +screwless +scrimpit +scrives +scrounged +scrupulosities +sculduddery +scummy +scutcheoned +scyphi +seaconny +seambiter +seas +seawater +secessionists +secretest +secularism +sedentariness +sedums +seemer +segmenting +seisable +seizures +selenion +seligmannite +semball +semiantiministerial +semicarbazone +semicomical +semicyclic +semidried +semifloret +semihot +semimembranosus +seminole +semiparameter +semipronation +semiruin +semisolid +semitheological +semola +senectitude +sensationalistic +sensive +sentimentalists +separatum +septendecimal +septship +sequesters +serdabs +serglobulin +serioline +serological +serpentiferous +serrirostrate +servilities +sesquisulphide +settaine +severalize +sexangularly +sextets +shabbed +shadoof +shagreen +shalloons +shameworthy +shantey +sharers +shastri +shay +shedder +sheepshear +shelduck +sheltron +sheriffess +shielders +shilfa +shining +shipper +shirtmaker +shoalest +shoepac +shooting +shopworker +shorthander +shoupeltin +showily +shrewlike +shrinking +shucker +shuteye +sialostenosis +siciliana +side +sideronym +sidlingly +sigher +sigmatism +signifer +sikhara +silicified +silkiest +siltier +silverwork +simoleon +simplificative +sinarchism +single +sinistrodextral +sinuatedentate +siphonoglyphe +sires +sissyism +situate +sizeable +skats +skellat +skew +skiepper +skims +skippy +skivvies +skunkish +skyscraper's +slaister +slantways +slaty +sleazy +sleepwalker +slewing +slim +slipforming +slithered +sloke +slotted +slubberer +slumberers +slushiest +smaltines +smeariness +smifligation +smithydander +smoodger +smudginess +snagbush +snapbag +snatches +sneesh +sniffled +snitchers +snoop +snout's +snowmobiles +snuffles +soapers +sobproof +sociocentrism +sockman +sofa's +soilages +solarising +solecist +solfeggi +solifidianism +solomon +solvolysis +somebodies +somnambulism +sonderclass +sonnetting +soothsaid +sopor +sordidity +sororicidal +sosoish +soum +sourdines +southernly +sowable +spacesuits +spaewoman +spaniards +sparing +sparsile +spatling +spealbone +specification +spectator +spectroradiometry +speedier +spellers +spermatid +spermoduct +sphaerosome +spherical +sphinxianness +spicks +spigot +spinal +spinnakers +spinulescent +spiriferous +spirling +spitter +splashingly +splendourproof +splenoptosis +splotchier +spokeswomanship +spongewood +spookery +sporadical +sporophyll +sporule +sprag +spreeuw +springtail +sprug +spurgalling +spy +squaloid +square +squattocratic +squeg +squinnied +squirrelling +stabilizing +stadia +stagging +staircases +stalkable +stampable +standings +stapedial +starchedly +starnie +stash +statical +statures +staying +steamed +steedlike +steeples +stele +stenchion +stenter +steppingstones +stereographer +stereotelemeter +sternebrae +stet +stibblerig +stickseed +stigmatizer +stime +stinkhorn +stipulatory +stocah +stockpots +stolelike +stomatograph +stoneless +stooled +storage +storms +stovehouse +strafes +straitening +strangulated +straticulate +strawless +streek +strepitous +strewment +stridulent +stringing +strobilate +strongfully +strouthocamelian +strung +stuccoer +stuffings +stunsle +sturniform +stylistics +styraxes +subadult +subarcuate +subbrachycephalic +subcheliform +subcommunities +subcorporation +subdefinitions +subdivine +subencephalon +subfalcial +subgenual +subhyoidean +subitaneous +subkingdom +sublimes +submental +submountain +suborbitar +subpenaing +subprocess +subrent +subscription +subshrubs +subspecifically +substitutions +subteen +subtilizer +subtriplicated +subvassal +succedaneous +succorer +suckered +sudor +suffixation +sugarcoated +suicidism +sulfacid +sulfogermanate +sulk +sulphatize +sulphogermanic +sulphovinic +sultans +summerhouses +sumptuous +sundogs +sunroofs +superabundances +superarctic +supercatastrophe +superconsecrated +supereconomy +superexcellently +superflux +superhumans +superinsist +supermagnificent +supernotable +superperson +superremuneration +superseminate +superspecialize +supersweet +supervisee +supplementally +supposableness +supraciliary +supranaturalism +supratrochlear +sure +surgeoness +surpeopled +surrogate's +suscept +suspiration +suturation +swaggy +swanhood +swarthness +sweal +sweetbriers +swelltoad +swimminess +swinking +swithly +swordlet +syconid +syllogistical +symbiotism +symmorphism +symphyogenesis +synagogical +synaxis +synclinore +syndetical +synergism +synonymes +syntheses +syphilized +systatic +tabaret +tablelike +tabu +tachyglossal +tackling +taenian +taguan +tailorhood +tajes +tald +talking +tallywalka +tamaricaceous +tampala +tangent's +tanistic +tannometer +taotai +tapings +tarantism +targetlike +tarpaulins +tarsus +taryard +tasteably +tattler +taurus +tautozonal +taxably +taxonom +teacheress +teapoys +teashops +technicological +tedded +teeters +tehsildar +teledendrion +telemetrist +telephony +telethermometry +teliosporic +teloteropathic +tempered +temporize +tenacity +tenderling +tenets +tenorites +tentaculocyst +tenurial +teratological +teredos +terminative +terp +terrenely +terrorist's +tessellates +testiculated +tetanizing +tetrachloroethylene +tetragrammatonic +tetrapharmacal +tetrasubstituted +teughly +thairms +thalthan +thar +theater's +theer +themelet +theolatrous +theophany +theory +therefore +thermantic +thermogenic +thermoreceptor +thesaurus +thiazoline +thight +thinkingpart +thionation +thirsted +tholed +thoracostracous +thoroughwax +thrashers +threefold +thrillers +thrombocytes +throwbacks +thulia +thunderheads +thwacks +thymuses +thyroparathyroidectomize +tibourbou +tickweed +tidyism +tigerkin +tile +timaraus +timeliness +tinampipi +tinglier +tinseling +tipcats +tipup +titaness +titillation +tittuppy +toadstool +tochered +toff +toiletted +tolerances +toluides +tomcats +toned +tonights +tonsured +toothbrush's +topchrome +topman +toprope +tordrillite +torolillo +torridness +tortuosity +tostication +totipotential +tougheners +tousche +towerwork +towny +toxigenicities +toytown +trachelomastoid +trachytoid +trade +traducianistic +traguline +trait's +tramp +tranquillest +transcending +transfashion +transformingly +transire +translocate +transmontane +transpirative +transpour +transvenom +trapezoidiform +traumaticine +travestiment +treasured +treeless +trembly +trendy +trestles +triangle +tribe +tributorian +trichites +trichorrhexic +tricksiness +tricycle +trifacial +triglochid +trihemiobol +trilling +trimetrical +trinitroresorcin +trioxazine +tripinnatifid +tripped +trisected +tristichs +tritocerebral +triunsaturated +trochiform +trogs +tromple +trophochromatin +tropophil +troublously +troweling +truculencies +trumperiness +trunnions +truthiness +trytophan +tuba +tuberculinization +tubiporid +tuckahoes +tugui +tumblings +tunbellied +tunket +turbaned +turboprops +turjaite +turniplike +turricular +tussle +tutster +twank +twelfthly +twilled +twirl +twitty +tymbals +typewrited +typic +tyrannically +tzardoms +udometries +ulcerated +ulsterette +ultraenthusiastic +ultramicrotome +ultrasonogram +umbellets +umbrellalike +unabject +unaccord +unactively +unadorn +unaffrightedly +unallegorical +unamo +unanswerable +unapposite +unarisen +unassailable +unattainableness +unavailingly +unbalanceable +unbeaded +unbegun +unbenumb +unbinds +unblooming +unborn +unbraved +unbruised +unbush +uncanned +uncasing +uncereclothed +uncharily +unchiselled +uncircumscribable +uncleaned +unclogs +uncoffle +uncomely +uncompassable +uncompromisingly +unconditionately +unconglobated +unconsolable +uncontentable +unconventionality +uncorrect +uncourting +uncredulous +unctiousness +uncuth +undebilitated +undecorously +undefrauded +undemonstrative +underagent +underbreathing +underclassmen +underdead +underestimations +undergaoler +underhang +underletter +underminer +underpier +underqualified +underscript +undersill +understay +underteacher +underverse +undescried +undethronable +undignify +undiscolored +undismounted +undissuade +undivisible +undoubtedness +undrossy +undying +uneffectible +unemancipated +unenchant +unennobled +unepauleted +unescapably +uneverted +unexcommunicated +unexpectable +unexpressibly +unfactitious +unfarced +unfeather +unfertile +unfingered +unflavored +unfocused +unforeseenly +unfortunates +unfrictioned +unfulsome +ungamboling +ungentlewomanlike +unglobular +ungovernably +ungreen +unguidably +unhallowing +unharnesses +unhearty +unhid +unhonest +unhumbled +uniaxial +unidentifiably +uniformization +unimaginative +unimpelled +unimuscular +uninerved +uninitiation +unintellectual +uninterruption +uninweaved +uniquity +unitarism +universes +unjoyously +unkindest +unlaboring +unlawed +unlettable +unlimitable +unloath +unlovingness +unmakable +unmarine +unmeasurably +unmenstruating +unmighty +unmistrusted +unmollifying +unmovability +unmysticize +unneglected +unnoted +unobstinate +unomitted +unoriginality +unpacifiable +unparallelable +unpassing +unpedigreed +unperiodical +unpetal +unpimpled +unplayable +unpoetize +unpossessively +unpredict +unpreservable +unprobated +unpromised +unprosperousness +unpulleyed +unqualifiable +unquitted +unravished +unreceivable +unred +unregainable +unreliableness +unrenownedness +unreproachableness +unresolved +unretracted +unrhythmic +unrippled +unrotund +unrustling +unsampled +unsatisfyingly +unschematized +unscrutinizing +unsee +unseparate +unshakably +unshelve +unshrivelled +unsimplify +unslammed +unsmokified +unsoiledness +unsorry +unspeculating +unspontaneously +unstaid +unstealthy +unstonable +unstrip +unsubsided +unsuitably +unsurcharge +unswathed +unsystematic +untar +untemptability +untheatrical +unthrones +untiring +untownlike +untransmissible +untripped +untumefied +ununderstandably +unvalidating +unveracious +unvisibly +unwading +unwasted +unweelness +unwigged +unwits +unwoundableness +upalley +upbuild +updarted +upgaze +upholstered +uploadable +upraisers +uprushing +upsplash +upsurging +upturned +uranate +urase +ureameter +ureterolithic +urethroscopical +urinocryoscopy +urogenic +uroseptic +urushic +usneas +uswards +utilitarianize +utterly +vacates +vacual +vagina +vaguer +valeramide +valkyrie +valueless +vanadiate +vanishment +vaporizer +variatious +variolovaccine +vasculose +vasotrophic +vaudevillist +vectorially +vegetativeness +veinwise +velocities +vendibility +venery +venosities +ventriloqual +venules +verberate +verek +verite +vermonter +versable +versipel +vertigo +vesiculose +vestigiary +vetivers +vials +vibromassage +vicine +victualless +viewings +vilayets +villanously +vinculation +vinic +violater +viperishly +virginship +virtuefy +visceroskeletal +visioned +visuoauditory +vitiable +vitrioline +vivider +vizircraft +vociferates +voiturette +volitiency +volume +volvent +vortices +vowelizing +vulcanologist +vulvas +waddying +waffs +wagoned +wainwrights +wakefully +walkway +walter +wandoo +wanton +wardman +warlikely +warps +wart's +washings +wasteland +watchingly +waterier +waterweed +wave +waxchandler +waymaker +wealthmaking +weasands +weaves +wedgy +weeper +weighmen +welcomed +welsh +werewolves +wetchet +whamming +whatnots +wheelmaking +whelpling +wherrying +whiffs +whinestone +whippy +whirrs +whistles +whitesmith +whizbang +whooplas +whup +widdie +wieldy +wiglets +wilfully +wills +windbreaks +window +wineglass +wingtip +winterdykes +wirebird +wisconsinites +wiskinky +witcraft +withinward +wittings +woddie +wolfskin +wombstone +wonting +woodhacker +woodsilver +woollier +wordable +workbox +workwise +worricow +worthinesses +wracker +wreak +wretched +wristlets +wrongheadedly +wurtzilite +xanthine +xanthyl +xeranthemum +xiphiplastron +xylogen +yabbering +yakka +yappy +yashmacs +yday +yeld +yenning +yetis +yobi +yokeless +youngest +yowt +yuppie +zamias +zax +zeiss +zested +zillionth +zinkenite +zoacum +zoned +zoogeographic +zoometries +zoophytography +zorilla +zygomatic +zymogens diff --git a/src/test/resources/htsjdk/samtools/io/example.bam b/src/test/resources/htsjdk/samtools/io/example.bam new file mode 100644 index 0000000000..18b96c15cc Binary files /dev/null and b/src/test/resources/htsjdk/samtools/io/example.bam differ diff --git a/src/test/resources/htsjdk/samtools/io/ipsum.txt b/src/test/resources/htsjdk/samtools/io/ipsum.txt new file mode 100644 index 0000000000..af0c95d8db --- /dev/null +++ b/src/test/resources/htsjdk/samtools/io/ipsum.txt @@ -0,0 +1,9 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vel justo nulla. Vestibulum ac dignissim justo. Fusce facilisis nisi aliquet, convallis erat et, tempus nulla. Maecenas vitae posuere turpis, pulvinar placerat ante. Curabitur consequat lacinia sapien, a molestie justo pharetra vitae. Quisque id orci orci. Proin velit urna, placerat quis sapien eget, hendrerit pretium urna. Nam vel risus fringilla, sodales purus eget, faucibus libero. Sed pharetra elit quis neque scelerisque, nec pellentesque nulla posuere. Vivamus congue tempor sem quis luctus. Etiam aliquam aliquet quam, sit amet interdum nibh interdum in. + +Curabitur vel tellus egestas, tincidunt lectus ut, interdum lectus. Praesent pharetra tincidunt est sed egestas. Integer in lorem ante. Sed ac eros felis. Ut id ex ex. Nam at ex nisl. Ut turpis magna, porttitor quis accumsan quis, varius a turpis. Sed vitae lectus in diam condimentum blandit hendrerit eu eros. Sed convallis efficitur consequat. Pellentesque sed pharetra nunc. + +Etiam ullamcorper urna laoreet dolor egestas elementum. Sed malesuada at augue nec vulputate. Donec placerat pellentesque ante, nec laoreet purus vulputate vel. Proin imperdiet, tellus eget accumsan euismod, nunc ipsum varius neque, id tincidunt urna ipsum non felis. In quam quam, ornare ut tincidunt quis, rutrum sed quam. Quisque ultrices justo dolor, eu pellentesque nibh sagittis et. Aenean feugiat elit arcu, ac sagittis dolor dignissim id. + +Sed sollicitudin turpis non sem viverra iaculis. Suspendisse vestibulum, lectus id interdum rutrum, justo leo ornare felis, eu varius lectus felis eget lectus. Nam eget lectus mollis, ultricies lorem semper, gravida enim. Duis condimentum, leo eget maximus convallis, mi mi molestie augue, sit amet ornare urna velit cursus orci. Nulla facilisi. Praesent dapibus elit ligula, a tristique leo commodo non. Quisque feugiat consequat blandit. Etiam mattis eros non tellus viverra, vel imperdiet elit venenatis. Fusce laoreet feugiat pharetra. Integer fermentum neque sit amet viverra suscipit. Nullam sed aliquam augue. Quisque augue libero, accumsan nec lorem non, iaculis bibendum ipsum. Nunc vel pulvinar felis. Nulla congue justo ut magna commodo cursus. Cras ullamcorper pulvinar lacus, id rhoncus neque eleifend quis. Nam vitae mi ullamcorper, malesuada purus eget, pharetra ipsum. + +Cras ante metus, molestie ut congue nec, sagittis eget nisi. Vestibulum pellentesque eleifend dui blandit feugiat. Integer nec lacinia odio, ut efficitur mauris. Vivamus laoreet sodales eros, sed feugiat mauris viverra ac. Proin interdum quam sit amet nibh faucibus, sit amet pellentesque velit accumsan. Donec hendrerit tincidunt sem, porttitor mollis erat rutrum et. Morbi et mollis erat. diff --git a/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgz b/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgz new file mode 100644 index 0000000000..c24ec20578 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgz differ diff --git a/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgz.wrongextension b/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgz.wrongextension new file mode 100644 index 0000000000..c24ec20578 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgz.wrongextension differ diff --git a/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgzipped_with_gzextension.gz b/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgzipped_with_gzextension.gz new file mode 100644 index 0000000000..c24ec20578 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/io/ipsum.txt.bgzipped_with_gzextension.gz differ diff --git a/src/test/resources/htsjdk/samtools/io/ipsum.txt.gz b/src/test/resources/htsjdk/samtools/io/ipsum.txt.gz new file mode 100644 index 0000000000..8546c04a1a Binary files /dev/null and b/src/test/resources/htsjdk/samtools/io/ipsum.txt.gz differ diff --git a/src/test/resources/htsjdk/samtools/one-contig.fasta b/src/test/resources/htsjdk/samtools/one-contig.fasta new file mode 100644 index 0000000000..8af5b5bf26 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/one-contig.fasta @@ -0,0 +1,278 @@ +>chr1 +GATCACAGGTCTATCACCCTATTAACCACTCACGGGAGCTCTCCATGCATTTGGTATTTT +CGTCTGGGGGGTGTGCACGCGATAGCATTGCGAGACGCTGGAGCCGGAGCACCCTATGTC +GCAGTATCTGTCTTTGATTCCTGCCTCATTCTATTATTTATCGCACCTACGTTCAATATT +ACAGGCGAACATACCTACTAAAGTGTGTTAATTAATTAATGCTTGTAGGACATAATAATA +ACAATTGAATGTCTGCACAGCCGCTTTCCACACAGACATCATAACAAAAAATTTCCACCA +AACCCCCCCCTCCCCCCGCTTCTGGCCACAGCACTTAAACACATCTCTGCCAAACCCCAA +AAACAAAGAACCCTAACACCAGCCTAACCAGATTTCAAATTTTATCTTTAGGCGGTATGC +ACTTTTAACAGTCACCCCCCAACTAACACATTATTTTCCCCTCCCACTCCCATACTACTA +ATCTCATCAATACAACCCCCGCCCATCCTACCCAGCACACACACACCGCTGCTAACCCCA +TACCCCGAACCAACCAAACCCCAAAGACACCCCCCACAGTTTATGTAGCTTACCTCCTCA +AAGCAATACACTGAAAATGTTTAGACGGGCTCACATCACCCCATAAACAAATAGGTTTGG +TCCTAGCCTTTCTATTAGCTCTTAGTAAGATTACACATGCAAGCATCCCCGTTCCAGTGA +GTTCACCCTCTAAATCACCACGATCAAAAGGGACAAGCATCAAGCACGCAGCAATGCAGC +TCAAAACGCTTAGCCTAGCCACACCCCCACGGGAAACAGCAGTGATTAACCTTTAGCAAT +AAACGAAAGTTTAACTAAGCTATACTAACCCCAGGGTTGGTCAATTTCGTGCCAGCCACC +GCGGTCACACGATTAACCCAAGTCAATAGAAGCCGGCGTAAAGAGTGTTTTAGATCACCC +CCTCCCCAATAAAGCTAAAACTCACCTGAGTTGTAAAAAACTCCAGTTGACACAAAATAG +ACTACGAAAGTGGCTTTAACATATCTGAACACACAATAGCTAAGACCCAAACTGGGATTA +GATACCCCACTATGCTTAGCCCTAAACCTCAACAGTTAAATCAACAAAACTGCTCGCCAG +AACACTACGAGCCACAGCTTAAAACTCAAAGGACCTGGCGGTGCTTCATATCCCTCTAGA +GGAGCCTGTTCTGTAATCGATAAACCCCGATCAACCTCACCACCTCTTGCTCAGCCTATA +TACCGCCATCTTCAGCAAACCCTGATGAAGGCTACAAAGTAAGCGCAAGTACCCACGTAA +AGACGTTAGGTCAAGGTGTAGCCCATGAGGTGGCAAGAAATGGGCTACATTTTCTACCCC +AGAAAACTACGATAGCCCTTATGAAACTTAAGGGTCGAAGGTGGATTTAGCAGTAAACTG +AGAGTAGAGTGCTTAGTTGAACAGGGCCCTGAAGCGCGTACACACCGCCCGTCACCCTCC +TCAAGTATACTTCAAAGGACATTTAACTAAAACCCCTACGCATTTATATAGAGGAGACAA +GTCGTAACATGGTAAGTGTACTGGAAAGTGCACTTGGACGAACCAGAGTGTAGCTTAACA +CAAAGCACCCAACTTACACTTAGGAGATTTCAACTTAACTTGACCGCTCTGAGCTAAACC +TAGCCCCAAACCCACTCCACCTTACTACCAGACAACCTTAGCCAAACCATTTACCCAAAT +AAAGTATAGGCGATAGAAATTGAAACCTGGCGCAATAGATATAGTACCGCAAGGGAAAGA +TGAAAAATTATAACCAAGCATAATATAGCAAGGACTAACCCCTATACCTTCTGCATAATG +AATTAACTAGAAATAACTTTGCAAGGAGAGCCAAAGCTAAGACCCCCGAAACCAGACGAG +CTACCTAAGAACAGCTAAAAGAGCACACCCGTCTATGTAGCAAAATAGTGGGAAGATTTA +TAGGTAGAGGCGACAAACCTACCGAGCCTGGTGATAGCTGGTTGTCCAAGATAGAATCTT +AGTTCAACTTTAAATTTGCCCACAGAACCCTCTAAATCCCCTTGTAAATTTAACTGTTAG +TCCAAAGAGGAACAGCTCTTTGGACACTAGGAAAAAACCTTGTAGAGAGAGTAAAAAATT +TAACACCCATAGTAGGCCTAAAAGCAGCCACCAATTAAGAAAGCGTTCAAGCTCAACACC +CACTACCTAAAAAATCCCAAACATATAACTGAACTCCTCACACCCAATTGGACCAATCTA +TCACCCTATAGAAGAACTAATGTTAGTATAAGTAACATGAAAACATTCTCCTCCGCATAA +GCCTGCGTCAGATCAAAACACTGAACTGACAATTAACAGCCCAATATCTACAATCAACCA +ACAAGTCATTATTACCCTCACTGTCAACCCAACACAGGCATGCTCATAAGGAAAGGTTAA +AAAAAGTAAAAGGAACTCGGCAAACCTTACCCCGCCTGTTTACCAAAAACATCACCTCTA +GCATCACCAGTATTAGAGGCACCGCCTGCCCAGTGACACATGTTTAACGGCCGCGGTACC +CTAACCGTGCAaaggtagcataatcacttgttccttaaatagggacctgtatgaatggct +ccacgagggttcagctgtctcttacttttaaccagtgaaattgacctgcccgtgaagagg +cgggcatgacacagcaagacgagaagaccctatggagctttaatttaTTAATGCAAACAG +TACCTAACAAACCCACAGGTCCTAAACTACCAAACCTGCATTAAAAATTTCGGTTGGGGC +GACCTCGGAGCAGAACCCAACCTCCGAGCAGTACATGCTAAGACTTCACCAGTCAAAGCG +AACTACTATACTCAATTGATCCAATAACTTGACCAACGGAACAAGTTACCCTAGGGATAA +CAGCGCAATCCTATTCTAGAGTCCATATCAACAATAGGGTTTACGACCTCGATGTTGGAT +CAGGACATCCCGATGGTGCAGCCGCTATTAAAGGTTCGTTTGTTCAACGATTAAAGTCCT +ACGTGATCTGAGTTCAGACCGGAGTAATCCAGGTCGGTTTCTATCTACTTCAAATTCCTC +CCTGTACGAAAGGACAAGAGAAATAAGGCCTACTTCACAAAGCGCCTTCCCCCGTAAATG +ATATCATCTCAACTTAGTATTATACCCACACCCACCCAAGAACAGGGTTTgttaagatgg +cagagcccggtaatcgcataaaacttaaaactttacagtcagaggttcaattcctcttct +taacaacaTACCCATGGCCAACCTCCTACTCCTCATTGTACCCATTCTAATCGCAATGGC +ATTCCTAATGCTTACCGAACGAAAAATTCTAGGCTATATACAACTACGCAAAGGCCCCAA +CGTTGTAGGCCCCTACGGGCTACTACAACCCTTCGCTGACGCCATAAAACTCTTCACCAA +AGAGCCCCTAAAACCCGCCACATCTACCATCACCCTCTACATCACCGCCCCGACCTTAGC +TCTCACCATCGCTCTTCTACTATGAACCCCCCTCCCCATACCCAACCCCCTGGTCAACCT +CAACCTAGGCCTCCTATTTATTCTAGCCACCTCTAGCCTAGCCGTTTACTCAATCCTCTG +ATCAGGGTGAGCATCAAACTCAAACTACGCCCTGATCGGCGCACTGCGAGCAGTAGCCCA +AACAATCTCATATGAAGTCACCCTAGCCATCATTCTACTATCAACATTACTAATAAGTGG +CTCCTTTAACCTCTCCACCCTTATCACAACACAAGAACACCTCTGATTACTCCTGCCATC +ATGACCCTTGGCCATAATATGATTTATCTCCACACTAGCAGAGACCAACCGAACCCCCTT +CGACCTTGCCGAAGGGGAGTCCGAACTAGTCTCAGGCTTCAACATCGAATACGCCGCAGG +CCCCTTCGCCCTATTCTTCATAGCCGAATACACAAACATTATTATAATAAACACCCTCAC +CACTACAATCTTCCTAGGAACAACATATGACGCACTCTCCCCTGAACTCTACACAACATA +TTTTGTCACCAAGACCCTACTTCTAACCTCCCTGTTCTTATGAATTCGAACAGCATACCC +CCGATTCCGCTACGACCAACTCATACACCTCCTATGAAAAAACTTCCTACCACTCACCCT +AGCATTACTTATATGATATGTCTCCATACCCATTACAATCTCCAGCATTCCCCCTCAAAC +CTAAGAAATATGTCTGATAAAAGAGTTACTTTGATAGAGTAAATAATAGGAGCTTAAACC +CCCTTATTTctaggactatgagaatcgaacccatccctgagaatccaaaattctccgtgc +cacctatcacaccccatcctaAAGTAAGGTCAGCTAAATAAGCTATCGGGCCCATACCCC +GAAAATGTTGGTTATACCCTTCCCGTACTAATTAATCCCCTGGCCCAACCCGTCATCTAC +TCTACCATCTTTGCAGGCACACTCATCACAGCGCTAAGCTCGCACTGATTTTTTACCTGA +GTAGGCCTAGAAATAAACATGCTAGCTTTTATTCCAGTTCTAACCAAAAAAATAAACCCT +CGTTCCACAGAAGCTGCCATCAAGTATTTCCTCACGCAAGCAACCGCATCCATAATCCTT +CTAATAGCTATCCTCTTCAACAATATACTCTCCGGACAATGAACCATAACCAATACTACC +AATCAATACTCATCATTAATAATCATAATGGCTATAGCAATAAAACTAGGAATAGCCCCC +TTTCACTTCTGAGTCCCAGAGGTTACCCAAGGCACCCCTCTGACATCCGGCCTGCTTCTT +CTCACATGACAAAAACTAGCCCCCATCTCAATCATATACCAAATCTCTCCCTCACTAAAC +GTAAGCCTTCTCCTCACTCTCTCAATCTTATCCATCATAGCAGGCAGTTGAGGTGGATTA +AACCAAACCCAGCTACGCAAAATCTTAGCATACTCCTCAATTACCCACATAGGATGAATA +ATAGCAGTTCTACCGTACAACCCTAACATAACCATTCTTAATTTAACTATTTATATTATC +CTAACTACTACCGCATTCCTACTACTCAACTTAAACTCCAGCACCACGACCCTACTACTA +TCTCGCACCTGAAACAAGCTAACATGACTAACACCCTTAATTCCATCCACCCTCCTCTCC +CTAGGAGGCCTGCCCCCGCTAACCGGCTTTTTGCCCAAATGGGCCATTATCGAAGAATTC +ACAAAAAACAATAGCCTCATCATCCCCACCATCATAGCCACCATCACCCTCCTTAACCTC +TACTTCTACCTACGCCTAATCTACTCCACCTCAATCACACTACTCCCCATATCTAACAAC +GTAAAAATAAAATGACAGTTTGAACATACAAAACCCACCCCATTCCTCCCCACACTCATC +GCCCTTACCACGCTACTCCTACCTATCTCCCCTTTTATACTAATAATCTTATAGAAATTT +AGGTTAAATACAGACCAAGAGCCTTCAAAGCCCTCAGTAAGTTGCAATACTTAATTTCTG +CAACAGCTAAGGACTGCAAAACCCCACTCTGCATCAACTGAACGCAAATCAGCCACTTTA +ATTAAGCTAAGCCCTTACTAGACCAATGGGACTTAAACCCACAAACACTTAGTTAACAGC +TAAGCACCCTAATCAACTGGCTTCAATCTACTTCTCCCGCCGCCGGGAAAAAAGGCGGGA +GAAGCCCCGGCAGGTTTGAAGCTGCTTCTTCGAATTTGCAATTCAATATGAAAATCACCT +CGGAGCTGGTAAAAAGAGGCCTAACCCCTGTCTTTAGATTTACAGTCCAATGCTTCACTC +AGCCATTTTACCTCACCCCCACTGATGTTCGCCGACCGTTGACTATTCTCTACAAACCAC +AAAGACATTGGAACACTATACCTATTATTCGGCGCATGAGCTGGAGTCCTAGGCACAGCT +CTAAGCCTCCTTATTCGAGCCGAGCTGGGCCAGCCAGGCAACCTTCTAGGTAACGACCAC +ATCTACAACGTTATCGTCACAGCCCATGCATTTGTAATAATCTTCTTCATAGTAATACCC +ATCATAATCGGAGGCTTTGGCAACTGACTAGTTCCCCTAATAATCGGTGCCCCCGATATG +GCGTTTCCCCGCATAAACAACATAAGCTTCTGACTCTTACCTCCCTCTCTCCTACTCCTG +CTCGCATCTGCTATAGTGGAGGCCGGAGCAGGAACAGGTTGAACAGTCTACCCTCCCTTA +GCAGGGAACTACTCCCACCCTGGAGCCTCCGTAGACCTAACCATCTTCTCCTTACACCTA +GCAGGTGTCTCCTCTATCTTAGGGGCCATCAATTTCATCACAACAATTATCAATATAAAA +CCCCCTGCCATAACCCAATACCAAACGCCCCTCTTCGTCTGATCCGTCCTAATCACAGCA +GTCCTACTTCTCCTATCTCTCCCAGTCCTAGCTGCTGGCATCACTATACTACTAACAGAC +CGCAACCTCAACACCACCTTCTTCGACCCCGCCGGAGGAGGAGACCCCATTCTATACCAA +CACCTATTCTGATTTTTCGGTCACCCTGAAGTTTATATTCTTATCCTACCAGGCTTCGGA +ATAATCTCCCATATTGTAACTTACTACTCCGGAAAAAAAGAACCATTTGGATACATAGGT +ATGGTCTGAGCTATGATATCAATTGGCTTCCTAGGGTTTATCGTGTGAGCACACCATATA +TTTACAGTAGGAATAGACGTAGACACACGAGCATATTTCACCTCCGCTACCATAATCATC +GCTATCCCCACCGGCGTCAAAGTATTTAGCTGACTCGCCACACTCCACGGAAGCAATATG +AAATGATCTGCTGCAGTGCTCTGAGCCCTAGGATTCATCTTTCTTTTCACCGTAGGTGGC +CTGACTGGCATTGTATTAGCAAACTCATCACTAGACATCGTACTACACGACACGTACTAC +GTTGTAGCTCACTTCCACTATGTCCTATCAATAGGAGCTGTATTTGCCATCATAGGAGGC +TTCATTCACTGATTTCCCCTATTCTCAGGCTACACCCTAGACCAAACCTACGCCAAAATC +CATTTCACTATCATATTCATCGGCGTAAATCTAACTTTCTTCCCACAACACTTTCTCGGC +CTATCCGGAATGCCCCGACGTTACTCGGACTACCCCGATGCATACACCACATGAAACATC +CTATCATCTGTAGGCTCATTCATTTCTCTAACAGCAGTAATATTAATAATTTTCATGATT +TGAGAAGCCTTCGCTTCGAAGCGAAAAGTCCTAATAGTAGAAGAACCCTCCATAAACCTG +GAGTGACTATATGGATGCCCCCCACCCTACCACACATTCGAAGAACCCGTATACATAAAA +TCTAGACAaaaaaggaaggaatcgaaccccccaaagctggtttcaagccaaccccatggc +ctccatgactttttcAAAAAGGTATTAGAAAAACCATTTCATAACTTTGTCAAAGTTAAA +TTATAGGCTAAATCCTATATATCTTAATGGCACATGCAGCGCAAGTAGGTCTACAAGACG +CTACTTCCCCTATCATAGAAGAGCTTATCACCTTTCATGATCACGCCCTCATAATCATTT +TCCTTATCTGCTTCCTAGTCCTGTATGCCCTTTTCCTAACACTCACAACAAAACTAACTA +ATACTAACATCTCAGACGCTCAGGAAATAGAAACCGTCTGAACTATCCTGCCCGCCATCA +TCCTAGTCCTCATCGCCCTCCCATCCCTACGCATCCTTTACATAACAGACGAGGTCAACG +ATCCCTCCCTTACCATCAAATCAATTGGCCACCAATGGTACTGAACCTACGAGTACACCG +ACTACGGCGGACTAATCTTCAACTCCTACATACTTCCCCCATTATTCCTAGAACCAGGCG +ACCTGCGACTCCTTGACGTTGACAATCGAGTAGTACTCCCGATTGAAGCCCCCATTCGTA +TAATAATTACATCACAAGACGTCTTGCACTCATGAGCTGTCCCCACATTAGGCTTAAAAA +CAGATGCAATTCCCGGACGTCTAAACCAAACCACTTTCACCGCTACACGACCGGGGGTAT +ACTACGGTCAATGCTCTGAAATCTGTGGAGCAAACCACAGTTTCATGCCCATCGTCCTAG +AATTAATTCCCCTAAAAATCTTTGAAATAGGGCCCGTATTTACCCTATAGCACCCCCTCT +ACCCCCTCTAGAGCCCACTGTAAAGCTAACTTAGCATTAACCTTTTAAGTTAAAGATTAA +GAGAACCAACACCTCTTTACAGTGAAATGCCCCAACTAAATACTACCGTATGGCCCACCA +TAATTACCCCCATACTCCTTACACTATTCCTCATCACCCAACTAAAAATATTAAACACAA +ACTACCACCTACCTCCCTCACCAAAGCCCATAAAAATAAAAAATTATAACAAACCCTGAG +AACCAAAATGAACGAAAATCTGTTCGCTTCATTCATTGCCCCCACAATCCTAGGCCTACC +CGCCGCAGTACTGATCATTCTATTTCCCCCTCTATTGATCCCCACCTCCAAATATCTCAT +CAACAACCGACTAATCACCACCCAACAATGACTAATCAAACTAACCTCAAAACAAATGAT +AGCCATACACAACACTAAAGGACGAACCTGATCTCTTATACTAGTATCCTTAATCATTTT +TATTGCCACAACTAACCTCCTCGGACTCCTGCCTCACTCATTTACACCAACCACCCAACT +ATCTATAAACCTAGCCATGGCCATCCCCTTATGAGCGGGCGCAGTGATTATAGGCTTTCG +CTCTAAGATTAAAAATGCCCTAGCCCACTTCTTACCACAAGGCACACCTACACCCCTTAT +CCCCATACTAGTTATTATCGAAACCATCAGCCTACTCATTCAACCAATAGCCCTGGCCGT +ACGCCTAACCGCTAACATTACTGCAGGCCACCTACTCATGCACCTAATTGGAAGCGCCAC +CCTAGCAATATCAACCATTAACCTTCCCTCTACACTTATCATCTTCACAATTCTAATTCT +ACTGACTATCCTAGAAATCGCTGTCGCCTTAATCCAAGCCTACGTTTTCACACTTCTAGT +AAGCCTCTACCTGCACGACAACACATAATGACCCACCAATCACATGCCTATCATATAGTA +AAACCCAGCCCATGACCCCTAACAGGGGCCCTCTCAGCCCTCCTAATGACCTCCGGCCTA +GCCATGTGATTTCACTTCCACTCCATAACGCTCCTCATACTAGGCCTACTAACCAACACA +CTAACCATATACCAATGGTGGCGCGATGTAACACGAGAAAGCACATACCAAGGCCACCAC +ACACCACCTGTCCAAAAAGGCCTTCGATACGGGATAATCCTATTTATTACCTCAGAAGTT +TTTTTCTTCGCAGGATTTTTCTGAGCCTTTTACCACTCCAGCCTAGCCCCTACCCCCCAA +CTAGGAGGGCACTGGCCCCCAACAGGCATCACCCCGCTAAATCCCCTAGAAGTCCCACTC +CTAAACACATCCGTATTACTCGCATCAGGAGTATCAATCACCTGAGCTCACCATAGTCTA +ATAGAAAACAACCGAAACCAAATAATTCAAGCACTGCTTATTACAATTTTACTGGGTCTC +TATTTTACCCTCCTACAAGCCTCAGAGTACTTCGAGTCTCCCTTCACCATTTCCGACGGC +ATCTACGGCTCAACATTTTTTGTAGCCACAGGCTTCCACGGACTTCACGTCATTATTGGC +TCAACTTTCCTCACTATCTGCTTCATCCGCCAACTAATATTTCACTTTACATCCAAACAT +CACTTTGGCTTCGAAGCCGCCGCCTGATACTGGCATTTTGTAGATGTGGTTTGACTATTT +CTGTATGTCTCCATCTATTGATGAGGGTCTTACTCTTTTAGTATAAATAGTACCGTTAAC +TTCCAATTAACTAGTTTTGACAACATTCAAAAAAGAGTAATAAACTTCGCCTTAATTTTA +ATAATCAACACCCTCCTAGCCTTACTACTAATAATTATTACATTTTGACTACCACAACTC +AACGGCTACATAGAAAAATCCACCCCTTACGAGTGCGGCTTCGACCCTATATCCCCCGCC +CGCGTCCCTTTCTCCATAAAATTCTTCTTAGTAGCTATTACCTTCTTATTATTTGATCTA +GAAATTGCCCTCCTTTTACCCCTACCATGAGCCCTACAAACAACTAACCTGCCACTAATA +GTTATGTCATCCCTCTTATTAATCATCATCCTAGCCCTAAGTCTGGCCTATGAGTGACTA +CAAAAAGGATTAGACTGAGCCGAATTGGTATATAGTTTAAACAAAACGAATGATTTCGAC +TCATTAAATTATGATAATCATATTTACCAAATGCCCCTCATTTACATAAATATTATACTA +GCATTTACCATCTCACTTCTAGGAATACTAGTATATCGCTCACACCTCATATCCTCCCTA +CTATGCCTAGAAGGAATAATACTATCGCTGTTCATTATAGCTACTCTCATAACCCTCAAC +ACCCACTCCCTCTTAGCCAATATTGTGCCTATTGCCATACTAGTCTTTGCCGCCTGCGAA +GCAGCGGTGGGCCTAGCCCTACTAGTCTCAATCTCCAACACATATGGCCTAGACTACGTA +CATAACCTAAACCTACTCCAATGCTAAAACTAATCGTCCCAACAATTATATTACTACCAC +TGACATGACTTTCCAAAAAGCACATAATTTGAATCAACACAACCACCCACAGCCTAATTA +TTAGCATCATCCCCCTACTATTTTTTAACCAAATCAACAACAACCTATTTAGCTGTTCCC +CAACCTTTTCCTCCGACCCCCTAACAACCCCCCTCCTAATACTAACTACCTGACTCCTAC +CCCTCACAATCATGGCAAGCCAACGCCACTTATCCAGCGAACCACTATCACGAAAAAAAC +TCTACCTCTCTATACTAATCTCCCTACAAATCTCCTTAATTATAACATTCACAGCCACAG +AACTAATCATATTTTATATCTTCTTCGAAACCACACTTATCCCCACCTTGGCTATCATCA +CCCGATGAGGCAACCAGCCAGAACGCCTGAACGCAGGCACATACTTCCTATTCTACACCC +TAGTAGGCTCCCTTCCCCTACTCATCGCACTAATTTACACTCACAACACCCTAGGCTCAC +TAAACATTCTACTACTCACTCTCACTGCCCAAGAACTATCAAACTCCTGAGCCAACAACT +TAATATGACTAGCTTACACAATAGCTTTTATAGTAAAGATACCTCTTTACGGACTCCACT +TATGACTCCCTAAAGCCCATGTCGAAGCCCCCATCGCTGGGTCAATAGTACTTGCCGCAG +TACTCTTAAAACTAGGCGGCTATGGTATAATACGCCTCACACTCATTCTCAACCCCCTGA +CAAAACACATAGCCTACCCCTTCCTTGTACTATCCCTATGAGGCATAATTATAACAAGCT +CCATCTGCCTACGACAAACAGACCTAAAATCGCTCATTGCATACTCTTCAATCAGCCACA +TAGCCCTCGTAGTAACAGCCATTCTCATCCAAACCCCCTGAAGCTTCACCGGCGCAGTCA +TTCTCATAATCGCCCACGGACTCACATCCTCATTACTATTCTGCCTAGCAAACTCAAACT +ACGAACGCACTCACAGTCGCATCATAATCCTCTCTCAAGGACTTCAAACTCTACTCCCAC +TAATAGCTTTTTGATGACTTCTAGCAAGCCTCGCTAACCTCGCCTTACCCCCCACTATTA +ACCTACTGGGAGAACTCTCTGTGCTAGTAACCACGTTCTCCTGATCAAATATCACTCTCC +TACTTACAGGACTCAACATACTAGTCACAGCCCTATACTCCCTCTACATATTTACCACAA +CACAATGGGGCTCACTCACCCACCACATTAACAACATAAAACCCTCATTCACACGAGAAA +ACACCCTCATGTTCATACACCTATCCCCCATTCTCCTCCTATCCCTCAACCCCGACATCA +TTACCGGGTTTTCCTCTTGTAAATATAGTTTAACCAAAACATCAGATTGTGAATCTGACA +ACAGAGGCTTACGACCCCTTATTTACCGAGAAAGCTCACAAGAACTGCTAACTCATGCCC +CCATGTCTAACAACATGGCTTTCTCAACTTTTAAAGGATAACAGCTATCCATTGGTCTTA +GGCCCCAAAAATTTTGGTGCAACTCCAAATAAAAGTAATAACCATGCACACTACTATAAC +CACCCTAACCCTGACTTCCCTAATTCCCCCCATCCTTACCACCCTCGTTAACCCTAACAA +AAAAAACTCATACCCCCATTATGTAAAATCCATTGTCGCATCCACCTTTATTATCAGTCT +CTTCCCCACAACAATATTCATGTGCCTAGACCAAGAAGTTATTATCTCGAACTGACACTG +AGCCACAACCCAAACAACCCAGCTCTCCCTAAGCTTCAAACTAGACTACTTCTCCATAAT +ATTCATCCCTGTAGCATTGTTCGTTACATGGTCCATCATAGAATTCTCACTGTGATATAT +AAACTCAGACCCAAACATTAATCAGTTCTTCAAATATCTACTCATTTTCCTAATTACCAT +ACTAATCTTAGTTACCGCTAACAACCTATTCCAACTGTTCATCGGCTGAGAGGGCGTAGG +AATTATATCCTTCTTGCTCATCAGTTGATGATACGCCCGAGCAGATGCCAACACAGCAGC +CATTCAAGCAGTCCTATACAACCGTATCGGCGATATCGGTTTCATCCTCGCCTTAGCATG +ATTTATCCTACACTCCAACTCATGAGACCCACAACAAATAGCCCTTCTAAACGCTAATCC +AAGCCTCACCCCACTACTAGGCCTCCTCCTAGCAGCAGCAGGCAAATCAGCCCAATTAGG +TCTCCACCCCTGACTCCCCTCAGCCATAGAAGGCCCCACCCCAGTCTCAGCCCTACTCCA +CTCAAGCACTATAGTTGTAGCAGGAATCTTCTTACTCATCCGCTTCCACCCCCTAGCAGA +AAATAGCCCACTAATCCAAACTCTAACACTATGCTTAGGCGCTATCACCACTCTGTTCGC +AGCAGTCTGCGCCCTTACACAAAATGACATCAAAAAAATCGTAGCCTTCTCCACTTCAAG +TCAACTAGGACTCATAATAGTTACAATCGGCATCAACCAACCACACCTAGCATTCCTGCA +CATCTGTACCCACGCCTTCTTCAAAGCCATACTATTTATGTGCTCCGGGTCCATCATCCA +CAACCTTAACAATGAACAAGATATTCGAAAAATAGGAGGACTACTCAAAACCATACCTCT +CACTTCAACCTCCCTCACCATTGGCAGCCTAGCATTAGCAGGAATACCTTTCCTCACAGG +TTTCTACTCCAAAGACCACATCATCGAAACCGCAAACATATCATACACAAACGCCTGAGC +CCTATCTATTACTCTCATCGCTACCTCCCTGACAAGCGCCTATAGCACTCGAATAATTCT +TCTCACCCTAACAGGTCAACCTCGCTTCCCCACCCTTACTAACATTAACGAAAATAACCC +CACCCTACTAAACCCCATTAAACGCCTGGCAGCCGGAAGCCTATTCGCAGGATTTCTCAT +TACTAACAACATTTCCCCCGCATCCCCCTTCCAAACAACAATCCCCCTCTACCTAAAACT +CACAGCCCTCGCTGTCACTTTCCTAGGACTTCTAACAGCCCTAGACCTCAACTACCTAAC +CAACAAACTTAAAATAAAATCCCCACTATGCACATTTTATTTCTCCAACATACTCGGATT +CTACCCTAGCATCACACACCGCACAATCCCCTATCTAGGCCTTCTTACGAGCCAAAACCT +GCCCCTACTCCTCCTAGACCTAACCTGACTAGAAAAGCTATTACCTAAAACAATTTCACA +GCACCAAATCTCCACCTCCATCATCACCTCAACCCAAAAAGGCATAATTAAACTTTACTT +CCTCTCTTTCTTCTTCCCACTCATCCTAACCCTACTCCTAATCACATAACCTATTCCCCC +GAGCAATCTCAATTACAATATATACACCAACAAACAATGTTCAACCAGTAACCACTACTA +ATCAACGCCCATAATCATACAAAGCCCCCGCACCAATAGGATCCTCCCGAATCAACCCTG +ACCCCTCTCCTTCATAAATTATTCAGCTTCCTACACTATTAAAGTTTACCACAACCACCA +CCCCATCATACTCTTTCACCCACAGCACCAATCCTACCTCCATCGCTAACCCCACTAAAA +CACTCACCAAGACCTCAACCCCTGACCCCCATGCCTCAGGATACTCCTCAATAGCCATCG +CTGTAGTATATCCAAAGACAACCATCATTCCCCCTAAATAAATTAAAAAAACTATTAAAC +CCATATAACCTCCCCCAAAATTCAGAATAATAACACACCCGACCACACCGCTAACAATCA +GTACTAAACCCCCATAAATAGGAGAAGGCTTAGAAGAAAACCCCACAAACCCCATTACTA +AACCCACACTCAACAGAAACAAAGCATACATCATTATTCTCGCACGGACTACAACCACGA +CCAATGATATGAAAAACCATCGTTGTATTTCAACTACAAGAACACCAATGACCCCAATAC +GCAAAATTAACCCCCTAATAAAATTAATTAACCACTCATTCATCGACCTCCCCACCCCAT +CCAACATCTCCGCATGATGAAACTTCGGCTCACTCCTTGGCGCCTGCCTGATCCTCCAAA +TCACCACAGGACTATTCCTAGCCATACACTACTCACCAGACGCCTCAACCGCCTTTTCAT +CAATCGCCCACATCACTCGAGACGTAAATTATGGCTGAATCATCCGCTACCTTCACGCCA +ATGGCGCCTCAATATTCTTTATCTGCCTCTTCCTACACATCGGGCGAGGCCTATATTACG +GATCATTTCTCTACTCAGAAACCTGAAACATCGGCATTATCCTCCTGCTTGCAACTATAG +CAACAGCCTTCATAGGCTATGTCCTCCCGTGAGGCCAAATATCATTCTGAGGGGCCACAG +TAATTACAAACTTACTATCCGCCATCCCATACATTGGGACAGACCTAGTTCAATGAATCT +GAGGAGGCTACTCAGTAGACAGTCCCACCCTCACACGATTCTTTACCTTTCACTTCATCT +TACCCTTCATTATTGCAGCCCTAGCAGCACTCCACCTCCTATTCTTGCACGAAACGGGAT +CAAACAACCCCCTAGGAATCACCTCCCATTCCGATAAAATCACCTTCCACCCTTACTACA +CAATCAAAGACGCCCTCGGCTTACTTCTCTTCCTTCTCTCCTTAATGACATTAACACTAT +TCTCACCAGACCTCCTAGGCGACCCAGACAATTATACCCTAGCCAACCCCTTAAACACCC +CTCCCCACATCAAGCCCGAATGATATTTCCTATTCGCCTACACAATTCTCCGATCCGTCC +CTAACAAACTAGGAGGCGTCCTTGCCCTATTACTATCCATCCTCATCCTAGCAATAATCC +CCATCCTCCATATATCCAAACAACAAAGCATAATATTTCGCCCACTAAGCCAATCACTTT +ATTGACTCCTAGCCGCAGACCTCCTCATTCTAACCTGAATCGGAGGACAACCAGTAAGCT +ACCCTTTTACCATCATTGGACAAGTAGCATCCGTACTATACTTCACAACAATCCTAATCC +TAATACCAACTATCTCCCTAATTGAAAACAAAATACTCAAATGGGCCTGTCCTTGTAGTA +TAAACTAATACACCAGTCTTGTAAACCGGAGACGAAAACCTTTTTCCAAGGACAAATCAG +AGAAAAAGTCTTTAACTCCACCATTAGCACCCAAAGCTAAGATTCTAATTTAAACTATTC +TCTGTTCTTTCATGGGGAAGCAGATTTGGGTACCACCCAAGTATTGACTCACCCATCAAC +AACCGCTATGTATTTCGTACATTACTGCCAGCCACCATGAATATTGTACGGTACCATAAA +TACTTGACCACCTGTAGTACATAAAAACCCAACCCACATCAAACCCCCCCCCCCCATGCT +TACAAGCAAGTACAGCAATCAACCTTCAACTATCACACATCAACTGCAACTCCAAAGCCA +CCCCTCACCCACTAGGATACCAACAAACCTACCCACCCTTAACAGTACATAGTACATAAA +GTCATTTACCGTACATAGCACATTACAGTCAAATCCCTTCTCGTCCCCATGGATGACCCC +CCTCAGATAGGGGTCCCTTGACCACCATCCTCCGTGAAATCAATATCCCGCACAAGAGTG +CTACTCTCCTCGCTCCGGGCCCATAACACTTGGGGGTAGCTAAAGTGAACTGTATCCGAC +ATCTGGTTCCTACTTCAGGGCCATAAAGCCTAAATAGCCCACACGTTCCCCTTAAATAAG +ACATCACGATG \ No newline at end of file diff --git a/src/test/resources/htsjdk/samtools/one-contig.fasta.fai b/src/test/resources/htsjdk/samtools/one-contig.fasta.fai new file mode 100644 index 0000000000..d626db67d6 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/one-contig.fasta.fai @@ -0,0 +1 @@ +chr1 16571 6 60 61 diff --git a/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.nogzindex.fasta.gz b/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.nogzindex.fasta.gz new file mode 100644 index 0000000000..aa8ef591b0 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.nogzindex.fasta.gz differ diff --git a/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.nogzindex.fasta.gz.fai b/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.nogzindex.fasta.gz.fai new file mode 100644 index 0000000000..04a438b940 --- /dev/null +++ b/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.nogzindex.fasta.gz.fai @@ -0,0 +1,2 @@ +chrM 16571 6 60 61 +chr20 1000000 16861 60 61 diff --git a/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.noindex.fasta.gz b/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.noindex.fasta.gz new file mode 100644 index 0000000000..aa8ef591b0 Binary files /dev/null and b/src/test/resources/htsjdk/samtools/reference/Homo_sapiens_assembly18.trimmed.noindex.fasta.gz differ diff --git a/src/test/resources/htsjdk/samtools/reference/simpleSmallFile.sam b/src/test/resources/htsjdk/samtools/reference/simpleSmallFile.sam new file mode 100644 index 0000000000..f37fe2525d --- /dev/null +++ b/src/test/resources/htsjdk/samtools/reference/simpleSmallFile.sam @@ -0,0 +1,8 @@ +@HD VN:1.0 SO:coordinate +@SQ SN:chrM LN:16571 UR:file:/Users/mhanna/src/Sting/Homo_sapiens_assembly18.trimmed.fasta M5:d2ed829b8a1628d16cbeee88e88e39eb +@SQ SN:chr20 LN:1000000 UR:file:/Users/mhanna/src/Sting/Homo_sapiens_assembly18.trimmed.fasta M5:b4eac854d70893986ac578c53c2324f1 +@RG ID:62A40.2 PL:illumina PU:62A40AAXX101028.2 LB:Solexa-45345 DT:2010-10-28T00:00:00-0400 SM:RRBS885 CN:BI +62A40AAXX101028:2:93:3981:7576 99 chrM 1 60 36M chrM 1 0 GATCACAGGTCTATCACCCTATTAACCACTCACGGG AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBB RG:Z:62A40.2 +62A40AAXX101028:2:93:3981:7576 147 chrM 1 60 36M chrM 1 0 GATCACAGGTCTATCACCCTATTAACCACTCACGGG BBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA RG:Z:62A40.2 +62A40AAXX101028:1:93:3981:7576 99 chr20 8401 60 60M chr20 8401 0 tgatctgtgcacaccactatccaaccgatcccgaggctccaccctggccactcttgtgtg AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAABBBBBBBBB RG:Z:62A40.2 +62A40AAXX101028:1:93:3981:7576 147 chr20 8401 60 60M chr20 8401 0 tgatctgtgcacaccactatccaaccgatcccgaggctccaccctggccactcttgtgtg BBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBAAAAAAAAAAAAAAAAAAAA RG:Z:62A40.2 diff --git a/src/test/resources/htsjdk/variant/corrupt_file_that_starts_with_#.vcf b/src/test/resources/htsjdk/variant/corrupt_file_that_starts_with_#.vcf new file mode 100644 index 0000000000..340e78a6e1 --- /dev/null +++ b/src/test/resources/htsjdk/variant/corrupt_file_that_starts_with_#.vcf @@ -0,0 +1,3 @@ +# +is not +a vcf \ No newline at end of file diff --git a/src/test/resources/htsjdk/variant/test_withGLandPL.vcf b/src/test/resources/htsjdk/variant/test_withGLandPL.vcf new file mode 100644 index 0000000000..5f0e5e7a6f --- /dev/null +++ b/src/test/resources/htsjdk/variant/test_withGLandPL.vcf @@ -0,0 +1,49 @@ +##fileformat=VCFv4.1 +##ApplyRecalibration="analysis_type=ApplyRecalibration input_file=[] read_buffer_size=null phone_home=NO_ET gatk_key=/humgen/gsa-hpprojects/GATK/data/gatk_user_keys/gsamembers_broadinstitute.org.key read_filter=[] intervals=null excludeIntervals=null interval_set_rule=UNION interval_merging=ALL interval_padding=0 reference_sequence=/humgen/gsa-hpprojects/GATK/bundle/current/b37/human_g1k_v37.fasta nonDeterministicRandomSeed=false downsampling_type=BY_SAMPLE downsample_to_fraction=null downsample_to_coverage=1000 baq=OFF baqGapOpenPenalty=40.0 performanceLog=null useOriginalQualities=false BQSR=null quantize_quals=0 disable_indel_quals=false emit_original_quals=false preserve_qscores_less_than=6 defaultBaseQualities=-1 validation_strictness=SILENT remove_program_records=false keep_program_records=false unsafe=null num_threads=1 num_cpu_threads=null num_io_threads=null num_bam_file_handles=null read_group_black_list=null pedigree=[] pedigreeString=[] pedigreeValidationType=STRICT allow_intervals_with_unindexed_bam=false generateShadowBCF=false logging_level=INFO log_to_file=null help=false input=[(RodBinding name=input source=/broad/hptmp/ami/tmp/CEUTrio_UG_Both_WG/CEUTrio.HiSeq.WGS.b37.listindel.unfiltered.vcf)] recal_file=(RodBinding name=recal_file source=/broad/hptmp/ami/tmp/CEUTrio_UG_Both_WG/CEUTrio.HiSeq.WGS.b37.listindel.recal) tranches_file=/broad/hptmp/ami/tmp/CEUTrio_UG_Both_WG/CEUTrio.HiSeq.WGS.b37.listindel.tranches out=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub no_cmdline_in_header=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub sites_only=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub bcf=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub ts_filter_level=95.0 ignore_filter=null mode=INDEL filter_mismatching_base_and_quals=false" +##CombineVariants="analysis_type=CombineVariants input_file=[] read_buffer_size=null phone_home=STANDARD gatk_key=null read_filter=[] intervals=null excludeIntervals=null interval_set_rule=UNION interval_merging=ALL interval_padding=0 reference_sequence=/humgen/gsa-hpprojects/GATK/bundle/current/b37/human_g1k_v37.fasta nonDeterministicRandomSeed=false downsampling_type=BY_SAMPLE downsample_to_fraction=null downsample_to_coverage=1000 baq=OFF baqGapOpenPenalty=40.0 performanceLog=null useOriginalQualities=false BQSR=null quantize_quals=0 disable_indel_quals=false emit_original_quals=false preserve_qscores_less_than=6 defaultBaseQualities=-1 validation_strictness=SILENT remove_program_records=false keep_program_records=false unsafe=null num_threads=1 num_cpu_threads=null num_io_threads=null num_bam_file_handles=null read_group_black_list=null pedigree=[] pedigreeString=[] pedigreeValidationType=STRICT allow_intervals_with_unindexed_bam=false generateShadowBCF=false logging_level=INFO log_to_file=null help=false variant=[(RodBinding name=variant source=CEUTrio.HiSeq.WGS.b37.listsnp.recalibrated.filtered.vcf), (RodBinding name=variant2 source=CEUTrio.HiSeq.WGS.b37.listindel.recalibrated.filtered.vcf)] out=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub no_cmdline_in_header=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub sites_only=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub bcf=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub genotypemergeoption=UNSORTED filteredrecordsmergetype=KEEP_IF_ANY_UNFILTERED multipleallelesmergetype=BY_TYPE rod_priority_list=null printComplexMerges=false filteredAreUncalled=false minimalVCF=false setKey=set assumeIdenticalSamples=true minimumN=1 suppressCommandLineHeader=false mergeInfoWithMaxAC=false filter_mismatching_base_and_quals=false" +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##PhaseByTransmission="analysis_type=PhaseByTransmission input_file=[] read_buffer_size=null phone_home=STANDARD gatk_key=null read_filter=[] intervals=null excludeIntervals=null interval_set_rule=UNION interval_merging=ALL interval_padding=0 reference_sequence=/humgen/gsa-hpprojects/GATK/bundle/current/b37/human_g1k_v37.fasta nonDeterministicRandomSeed=false downsampling_type=BY_SAMPLE downsample_to_fraction=null downsample_to_coverage=1000 baq=OFF baqGapOpenPenalty=40.0 performanceLog=null useOriginalQualities=false BQSR=null quantize_quals=0 disable_indel_quals=false emit_original_quals=false preserve_qscores_less_than=6 defaultBaseQualities=-1 validation_strictness=SILENT remove_program_records=false keep_program_records=false unsafe=null num_threads=1 num_cpu_threads=null num_io_threads=null num_bam_file_handles=null read_group_black_list=null pedigree=[/broad/hptmp/ami/tmp/CEUTrio.ped] pedigreeString=[] pedigreeValidationType=STRICT allow_intervals_with_unindexed_bam=false generateShadowBCF=false logging_level=INFO log_to_file=null help=false variant=(RodBinding name=variant source=/broad/hptmp/ami/tmp/CEUTrio_UG_Both_WG/CEUTrio.HiSeq.WGS.b37.snps_and_indels.recalibrated.filtered.vcf) DeNovoPrior=1.0E-8 FatherAlleleFirst=false out=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub no_cmdline_in_header=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub sites_only=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub bcf=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub filter_mismatching_base_and_quals=false" +##UnifiedGenotyper="analysis_type=UnifiedGenotyper input_file=[/humgen/gsa-hpprojects/NA12878Collection/bams/CEUTrio.HiSeq.WGS.b37.list] read_buffer_size=null phone_home=NO_ET gatk_key=/humgen/gsa-hpprojects/GATK/data/gatk_user_keys/gsamembers_broadinstitute.org.key read_filter=[] intervals=[/broad/hptmp/ami/tmp/queueScatterGather/.qlog/CEUTrio.indelcall-sg/temp_020_of_300/scatter.intervals] excludeIntervals=null interval_set_rule=UNION interval_merging=ALL interval_padding=0 reference_sequence=/humgen/gsa-hpprojects/GATK/bundle/current/b37/human_g1k_v37.fasta nonDeterministicRandomSeed=false downsampling_type=BY_SAMPLE downsample_to_fraction=null downsample_to_coverage=250 baq=OFF baqGapOpenPenalty=40.0 performanceLog=null useOriginalQualities=false BQSR=null quantize_quals=0 disable_indel_quals=false emit_original_quals=false preserve_qscores_less_than=6 defaultBaseQualities=-1 validation_strictness=SILENT remove_program_records=false keep_program_records=false unsafe=null num_threads=2 num_cpu_threads=null num_io_threads=null num_bam_file_handles=null read_group_black_list=null pedigree=[] pedigreeString=[] pedigreeValidationType=STRICT allow_intervals_with_unindexed_bam=false generateShadowBCF=false logging_level=INFO log_to_file=null help=false genotype_likelihoods_model=INDEL p_nonref_model=EXACT pcr_error_rate=1.0E-4 noSLOD=false annotateNDA=false min_base_quality_score=17 max_deletion_fraction=0.05 cap_max_alternate_alleles_for_indels=false min_indel_count_for_genotyping=5 min_indel_fraction_per_sample=0.25 indel_heterozygosity=1.25E-4 indelGapContinuationPenalty=10 indelGapOpenPenalty=45 indelHaplotypeSize=80 noBandedIndel=false indelDebug=false ignoreSNPAlleles=false allReadsSP=false ignoreLaneInfo=false reference_sample_calls=(RodBinding name= source=UNBOUND) reference_sample_name=null sample_ploidy=2 min_quality_score=1 max_quality_score=40 site_quality_prior=20 min_power_threshold_for_calling=0.95 min_reference_depth=100 exclude_filtered_reference_sites=false heterozygosity=0.0010 genotyping_mode=DISCOVERY output_mode=EMIT_VARIANTS_ONLY standard_min_confidence_threshold_for_calling=30.0 standard_min_confidence_threshold_for_emitting=30.0 alleles=(RodBinding name= source=UNBOUND) max_alternate_alleles=3 dbsnp=(RodBinding name=dbsnp source=/humgen/gsa-hpprojects/GATK/bundle/current/b37/dbsnp_135.b37.vcf) comp=[] out=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub no_cmdline_in_header=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub sites_only=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub bcf=org.broadinstitute.sting.gatk.io.stubs.VariantContextWriterStub debug_file=null metrics_file=null annotation=[] excludeAnnotation=[] filter_mismatching_base_and_quals=false" +##contig= +##contig= +##contig= +#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT NA12878 +chr1 6870 . C T 11.04 . AC=1;AF=0.500;AN=2;DP=16;FS=6.990;MQ=39.29;MQRankSum=-1.036;QD=0.69;ReadPosRankSum=-2.383;SOR=3.258;FractionInformativeReads=0.625;R2_5P_bias=31.099 GT:AD:AF:DP:GQ:PL:GL:GP:PRI:SB:MB 0/1:6,4:0.400:10:45:45,0,50:-4.55,0.00,-5.00:7.864e-02,9.214e-01,4.618e-06:0.00,34.77,37.77:3,3,0,4:4,2,1,3 \ No newline at end of file