Skip to content

Commit

Permalink
settable deflater factory
Browse files Browse the repository at this point in the history
  • Loading branch information
akiezun committed Jun 7, 2016
1 parent 6c273b4 commit 1e02905
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 242 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ cache:
- $HOME/.m2
jdk:
- oraclejdk8
script: ./gradlew jacocoTestReport testSRA testIntelDeflater;
script: ./gradlew jacocoTestReport testSRA;
after_success:
- echo "TRAVIS_BRANCH='$TRAVIS_BRANCH'";
echo "JAVA_HOME='$JAVA_HOME'";
Expand Down
22 changes: 2 additions & 20 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ plugins {

repositories {
mavenCentral()

// Include the Broad artifactory for intel-gkl snapshots. This is temporary
// until intel-gkl is available on maven central.
//maven {
// url "https://artifactory.broadinstitute.org/artifactory/libs-snapshot/"
//}
}

jacocoTestReport {
Expand All @@ -48,9 +42,6 @@ dependencies {
compile "org.tukaani:xz:1.5"
compile "gov.nih.nlm.ncbi:ngs-java:1.2.2"

// Disabled until intel-gkl is in maven central
// compile "com.intel:intel-gkl:0.0.1-20160525.160915-2"

testCompile "org.testng:testng:6.9.9"
}

Expand Down Expand Up @@ -126,22 +117,13 @@ test {

useTestNG {
if( OperatingSystem.current().isUnix() ){
excludeGroups "slow", "broken", "sra", "intel"
excludeGroups "slow", "broken", "sra"
} else {
excludeGroups "slow", "broken", "unix", "sra", "intel"
excludeGroups "slow", "broken", "unix", "sra"
}
}
}

task testIntelDeflater(type: Test){
jvmArgs '-Dsamjdk.try_use_intel_deflater=true'

description "Run the Intel Deflater tests"
useTestNG {
includeGroups "intel"
}
}

task testSRA(type: Test){
description "Run the SRA tests"
useTestNG{
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/htsjdk/samtools/BAMFileWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import htsjdk.samtools.util.BinaryCodec;
import htsjdk.samtools.util.BlockCompressedOutputStream;
import htsjdk.samtools.util.RuntimeIOException;
import htsjdk.samtools.util.zip.DeflaterFactory;

import java.io.DataOutputStream;
import java.io.File;
Expand Down Expand Up @@ -68,6 +69,12 @@ protected BAMFileWriter(final OutputStream os, final File file, final int compre
outputBinaryCodec.setOutputFileName(getPathString(file));
}

protected BAMFileWriter(final OutputStream os, final File file, final int compressionLevel, final DeflaterFactory deflaterFactory) {
blockCompressedOutputStream = new BlockCompressedOutputStream(os, file, compressionLevel, deflaterFactory);
outputBinaryCodec = new BinaryCodec(new DataOutputStream(blockCompressedOutputStream));
outputBinaryCodec.setOutputFileName(getPathString(file));
}

private void prepareToWriteAlignments() {
if (bamRecordCodec == null) {
bamRecordCodec = new BAMRecordCodec(getFileHeader());
Expand Down
5 changes: 0 additions & 5 deletions src/main/java/htsjdk/samtools/Defaults.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ public class Defaults {
*/
public static final int NON_ZERO_BUFFER_SIZE;

/** Should BlockCompressedOutputStream attempt to load libIntelDeflater? */
public static final boolean TRY_USE_INTEL_DEFLATER;

/**
* 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).
Expand Down Expand Up @@ -98,7 +95,6 @@ public class Defaults {
}
COMPRESSION_LEVEL = getIntProperty("compression_level", 5);
BUFFER_SIZE = getIntProperty("buffer_size", 1024 * 128);
TRY_USE_INTEL_DEFLATER = getBooleanProperty("try_use_intel_deflater", false);
if (BUFFER_SIZE == 0) {
NON_ZERO_BUFFER_SIZE = 1024 * 128;
} else {
Expand All @@ -124,7 +120,6 @@ public static SortedMap<String, Object> allDefaults(){
result.put("USE_ASYNC_IO_FOR_TRIBBLE", USE_ASYNC_IO_FOR_TRIBBLE);
result.put("COMPRESSION_LEVEL", COMPRESSION_LEVEL);
result.put("BUFFER_SIZE", BUFFER_SIZE);
result.put("TRY_USE_INTEL_DEFLATER", TRY_USE_INTEL_DEFLATER);
result.put("NON_ZERO_BUFFER_SIZE", NON_ZERO_BUFFER_SIZE);
result.put("REFERENCE_FASTA", REFERENCE_FASTA);
result.put("USE_CRAM_REF_DOWNLOAD", USE_CRAM_REF_DOWNLOAD);
Expand Down
19 changes: 17 additions & 2 deletions src/main/java/htsjdk/samtools/SAMFileWriterFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
import htsjdk.samtools.util.Log;
import htsjdk.samtools.util.Md5CalculatingOutputStream;
import htsjdk.samtools.util.RuntimeIOException;
import htsjdk.samtools.util.zip.DeflaterFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.Deflater;

/**
* Create a writer for writing SAM, BAM, or CRAM files.
Expand All @@ -51,6 +53,7 @@ public class SAMFileWriterFactory implements Cloneable {
/** compression level 0: min 9:max */
private int compressionLevel = BlockCompressedOutputStream.getDefaultCompressionLevel();
private Integer maxRecordsInRam = null;
private DeflaterFactory deflaterFactory = BlockCompressedOutputStream.getDefaultDeflaterFactory();

/** simple constructor */
public SAMFileWriterFactory() {
Expand Down Expand Up @@ -89,6 +92,18 @@ public SAMFileWriterFactory setCreateMd5File(final boolean createMd5File) {
return this;
}

/**
* Set the deflater factory used by BAM writers created by this writer factory. Must not be null.
* If this method is not called, the default {@link DeflaterFactory} is used which creates the default JDK {@link Deflater}.
* This method returns the SAMFileWriterFactory itself. */
public SAMFileWriterFactory setDeflaterFactory(final DeflaterFactory deflaterFactory){
if (deflaterFactory == null){
throw new IllegalArgumentException("null deflater factory");
}
this.deflaterFactory = deflaterFactory;
return this;
}

/** set compression level 0!none 9: max */
public SAMFileWriterFactory setCompressionLevel(final int compressionLevel) {
this.compressionLevel = Math.min(9, Math.max(0, compressionLevel));
Expand Down Expand Up @@ -206,7 +221,7 @@ public SAMFileWriter makeBAMWriter(final SAMFileHeader header, final boolean pre
}
OutputStream os = IOUtil.maybeBufferOutputStream(new FileOutputStream(outputFile, false), bufferSize);
if (createMd5File) os = new Md5CalculatingOutputStream(os, new File(outputFile.getAbsolutePath() + ".md5"));
final BAMFileWriter ret = new BAMFileWriter(os, outputFile, compressionLevel);
final BAMFileWriter ret = new BAMFileWriter(os, outputFile, compressionLevel, deflaterFactory);
final boolean createIndex = this.createIndex && IOUtil.isRegularPath(outputFile);
if (this.createIndex && !createIndex) {
log.warn("Cannot create index for BAM because output file is not a regular file: " + outputFile.getAbsolutePath());
Expand Down Expand Up @@ -282,7 +297,7 @@ public SAMFileWriter makeSAMWriter(final SAMFileHeader header, final boolean pre
*/

public SAMFileWriter makeBAMWriter(final SAMFileHeader header, final boolean presorted, final OutputStream stream) {
return initWriter(header, presorted, true, new BAMFileWriter(stream, null, this.getCompressionLevel()));
return initWriter(header, presorted, true, new BAMFileWriter(stream, null, this.getCompressionLevel(), this.deflaterFactory));
}

/**
Expand Down
7 changes: 1 addition & 6 deletions src/main/java/htsjdk/samtools/SamReaderFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@
import htsjdk.samtools.cram.ref.ReferenceSource;
import htsjdk.samtools.seekablestream.SeekableStream;
import htsjdk.samtools.sra.SRAAccession;
import htsjdk.samtools.util.BlockCompressedInputStream;
import htsjdk.samtools.util.BlockCompressedStreamConstants;
import htsjdk.samtools.util.CloserUtil;
import htsjdk.samtools.util.IOUtil;
import htsjdk.samtools.util.Log;
import htsjdk.samtools.util.RuntimeIOException;
import htsjdk.samtools.util.*;

import java.io.File;
import java.io.IOException;
Expand Down
10 changes: 2 additions & 8 deletions src/main/java/htsjdk/samtools/example/PrintReadsExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import htsjdk.samtools.*;
import htsjdk.samtools.util.Log;
import htsjdk.samtools.util.ProgressLogger;
import htsjdk.samtools.util.zip.DeflaterFactory;

import java.io.File;
import java.io.IOException;
Expand All @@ -39,11 +38,7 @@
* This is a example program showing how to use SAM readers and (optionally) writers.
* It's also useful for measuring time.
* An example invocation is:
* java -cp dist/htsjdk-2.1.1.jar htsjdk.samtools.example.PrintReadsExample in.bam false a.bam
* <p>
* or (to test the IntelDeflator)
* java -Dsamjdk.intel_deflater_so_path=$PWD/lib/jni/libIntelDeflater.so -cp dist/htsjdk-2.1.1.jar htsjdk.samtools.example.PrintReadsExample in.bam false a.bam
* <p>
* <code>java -cp dist/htsjdk-2.1.1.jar htsjdk.samtools.example.PrintReadsExample in.bam false a.bam</code>
* Arguments:
* - the first argument is the input file (SAM or BAM)
* - the second argument is a boolean (true or false) that indicates whether reads are to be eagerly decoded (useful for benchmarking)
Expand Down Expand Up @@ -95,8 +90,7 @@ private static void printConfigurationInfo() throws IOException {
System.getProperty("user.name") + '@' + InetAddress.getLocalHost().getHostName() +
" on " + System.getProperty("os.name") + ' ' + System.getProperty("os.version") +
' ' + System.getProperty("os.arch") + "; " + System.getProperty("java.vm.name") +
' ' + System.getProperty("java.runtime.version") +
' ' + (DeflaterFactory.usingIntelDeflater() ? "IntelDeflater loaded and available for Level 1 compression" : "Using JdkDeflater"));
' ' + System.getProperty("java.runtime.version"));

final List<String> list = Defaults.allDefaults().entrySet().stream().map(e -> e.getKey() + ':' + e.getValue()).collect(Collectors.toList());
log.info(String.join(" ", list));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class BlockCompressedOutputStream
private static final Log log = Log.getInstance(BlockCompressedOutputStream.class);

private static int defaultCompressionLevel = BlockCompressedStreamConstants.DEFAULT_COMPRESSION_LEVEL;
private static DeflaterFactory defaultDeflaterFactory = new DeflaterFactory();

/**
* Sets the GZip compression level for subsequent BlockCompressedOutputStream object creation
Expand All @@ -71,6 +72,22 @@ public static int getDefaultCompressionLevel() {
return defaultCompressionLevel;
}

/**
* Sets the default {@link DeflaterFactory} that will be used for all instances unless specified otherwise in the constructor.
* If this method is not called the default is a factory that will create the JDK {@link Deflater}.
* @param deflaterFactory non-null default factory.
*/
public static void setDefaultDeflaterFactory(final DeflaterFactory deflaterFactory) {
if (deflaterFactory == null) {
throw new IllegalArgumentException("null deflaterFactory");
}
defaultDeflaterFactory = deflaterFactory;
}

public static DeflaterFactory getDefaultDeflaterFactory() {
return defaultDeflaterFactory;
}

private final BinaryCodec codec;
private final byte[] uncompressedBuffer = new byte[BlockCompressedStreamConstants.DEFAULT_UNCOMPRESSED_BLOCK_SIZE];
private int numUncompressedBytes = 0;
Expand Down Expand Up @@ -102,20 +119,25 @@ public static int getDefaultCompressionLevel() {

/**
* Uses default compression level, which is 5 unless changed by setCompressionLevel
* Note: this constructor uses the default {@link DeflaterFactory}, see {@link #getDefaultDeflaterFactory()}.
* Use {@link #BlockCompressedOutputStream(File, int, DeflaterFactory)} to specify a custom factory.
*/
public BlockCompressedOutputStream(final String filename) {
this(filename, defaultCompressionLevel);
}

/**
* Uses default compression level, which is 5 unless changed by setCompressionLevel
* Note: this constructor uses the default {@link DeflaterFactory}, see {@link #getDefaultDeflaterFactory()}.
* Use {@link #BlockCompressedOutputStream(File, int, DeflaterFactory)} to specify a custom factory.
*/
public BlockCompressedOutputStream(final File file) {
this(file, defaultCompressionLevel);
}

/**
* Prepare to compress at the given compression level
* Note: this constructor uses the default {@link DeflaterFactory}, see {@link #getDefaultDeflaterFactory()}.
* @param compressionLevel 1 <= compressionLevel <= 9
*/
public BlockCompressedOutputStream(final String filename, final int compressionLevel) {
Expand All @@ -125,29 +147,58 @@ public BlockCompressedOutputStream(final String filename, final int compressionL
/**
* Prepare to compress at the given compression level
* @param compressionLevel 1 <= compressionLevel <= 9
* Note: this constructor uses the default {@link DeflaterFactory}, see {@link #getDefaultDeflaterFactory()}.
* Use {@link #BlockCompressedOutputStream(File, int, DeflaterFactory)} to specify a custom factory.
*/
public BlockCompressedOutputStream(final File file, final int compressionLevel) {
this(file, compressionLevel, defaultDeflaterFactory);
}

/**
* Prepare to compress at the given compression level
* @param compressionLevel 1 <= compressionLevel <= 9
* @param deflaterFactory custom factory to create deflaters (overrides the default)
*/
public BlockCompressedOutputStream(final File file, final int compressionLevel, final DeflaterFactory deflaterFactory) {
this.file = file;
codec = new BinaryCodec(file, true);
deflater = DeflaterFactory.makeDeflater(compressionLevel, true);
deflater = deflaterFactory.makeDeflater(compressionLevel, true);
log.debug("Using deflater: " + deflater.getClass().getSimpleName());
}

/**
* Constructors that take output streams
* file may be null
* Uses default compression level, which is 5 unless changed by setCompressionLevel
* Note: this constructor uses the default {@link DeflaterFactory}, see {@link #getDefaultDeflaterFactory()}.
* Use {@link #BlockCompressedOutputStream(OutputStream, File, int, DeflaterFactory)} to specify a custom factory.
*
* @param file may be null
*/
public BlockCompressedOutputStream(final OutputStream os, final File file) {
this(os, file, defaultCompressionLevel);
}

/**
* Note: this constructor uses the default {@link DeflaterFactory}, see {@link #getDefaultDeflaterFactory()}.
* Use {@link #BlockCompressedOutputStream(OutputStream, File, int, DeflaterFactory)} to specify a custom factory.
*/
public BlockCompressedOutputStream(final OutputStream os, final File file, final int compressionLevel) {
this(os, file, compressionLevel, defaultDeflaterFactory);
}

/**
* Creates the output stream.
* @param os output stream to create a BlockCompressedOutputStream from
* @param file file to which to write the output or null if not available
* @param compressionLevel the compression level (0-9)
* @param deflaterFactory custom factory to create deflaters (overrides the default)
*/
public BlockCompressedOutputStream(final OutputStream os, final File file, final int compressionLevel, final DeflaterFactory deflaterFactory) {
this.file = file;
codec = new BinaryCodec(os);
if (file != null) {
codec.setOutputFileName(file.getAbsolutePath());
}
deflater = DeflaterFactory.makeDeflater(compressionLevel, true);
deflater = deflaterFactory.makeDeflater(compressionLevel, true);
log.debug("Using deflater: " + deflater.getClass().getSimpleName());
}

Expand All @@ -160,9 +211,9 @@ public BlockCompressedOutputStream(final OutputStream os, final File file, final
*/
public static BlockCompressedOutputStream maybeBgzfWrapOutputStream(final File location, OutputStream output) {
if (!(output instanceof BlockCompressedOutputStream)) {
return new BlockCompressedOutputStream(output, location);
return new BlockCompressedOutputStream(output, location);
} else {
return (BlockCompressedOutputStream)output;
return (BlockCompressedOutputStream)output;
}
}

Expand Down
Loading

0 comments on commit 1e02905

Please sign in to comment.