Permalink
Browse files

adding additional write method to Index, fixes #430 (#683)

Adding Index.write(file) to the index interface.  

This is a breaking change which will affect anyone who implements Index or calls TabixFile.write.

This fixes an issue where IndexFactory.writeIndex was incorrectly failing to compress tabix index files.  
(fix #430 )

TabixIndex.write(file) now throws IOException instead of TribbleException.  This makes it consistent with the write(stream) methods.  Call sites must now catch or throw IOException.

deprecated IndexFactory.writeIndex(index, file) because it is now redundant, replace with index.write(file)
  • Loading branch information...
1 parent 0e6edc7 commit fbba5364e1809de071bc479f30e4e2c8b17f5bbe @magicDGS magicDGS committed with lbergelson Sep 16, 2016
@@ -343,13 +343,16 @@ public void write(final LittleEndianOutputStream stream) throws IOException {
}
@Override
+ public void write(final File idxFile) throws IOException {
+ try(final LittleEndianOutputStream idxStream = new LittleEndianOutputStream(new BufferedOutputStream(new FileOutputStream(idxFile)))) {
+ write(idxStream);
+ }
+ }
+
+ @Override
public void writeBasedOnFeatureFile(final File featureFile) throws IOException {
if (!featureFile.isFile()) return;
- final LittleEndianOutputStream idxStream =
- new LittleEndianOutputStream(new BufferedOutputStream(new FileOutputStream(Tribble.indexFile(featureFile))));
- write(idxStream);
- idxStream.close();
-
+ write(Tribble.indexFile(featureFile));
}
public void read(final LittleEndianInputStream dis) throws IOException {
@@ -70,6 +70,14 @@
public void write(LittleEndianOutputStream stream) throws IOException;
/**
+ * Writes the index into a file.
+ *
+ * @param idxFile Where to write the index.
+ * @throws IOException if the index is unable to write to the specified file
+ */
+ public void write(final File idxFile) throws IOException;
+
+ /**
* Write an appropriately named and located Index file based on the name and location of the featureFile.
* If featureFile is not a normal file, the index will silently not be written.
* @param featureFile
@@ -41,16 +41,13 @@
import htsjdk.tribble.index.tabix.TabixIndexCreator;
import htsjdk.tribble.readers.PositionalBufferedStream;
import htsjdk.tribble.util.LittleEndianInputStream;
-import htsjdk.tribble.util.LittleEndianOutputStream;
import htsjdk.tribble.util.ParsingUtils;
import htsjdk.tribble.util.TabixUtils;
import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
@@ -288,18 +285,11 @@ public static LinearIndex createLinearIndex(final File inputFile, final FeatureC
* @param idx
* @param idxFile
* @throws IOException
+ * @deprecated use {@link Index#write(File)} instead
*/
+ @Deprecated
public static void writeIndex(final Index idx, final File idxFile) throws IOException {
- LittleEndianOutputStream stream = null;
- try {
- stream = new LittleEndianOutputStream(new BufferedOutputStream(new FileOutputStream(idxFile)));
- idx.write(stream);
- }
- finally {
- if(stream != null) {
- stream.close();
- }
- }
+ idx.write(idxFile);
}
/**
@@ -201,13 +201,10 @@ public TabixFormat getFormatSpec() {
*
* @param tabixFile Where to write the index.
*/
- public void write(final File tabixFile) {
- final LittleEndianOutputStream los = new LittleEndianOutputStream(new BlockCompressedOutputStream(tabixFile));
- try {
+ @Override
+ public void write(final File tabixFile) throws IOException {
+ try(final LittleEndianOutputStream los = new LittleEndianOutputStream(new BlockCompressedOutputStream(tabixFile))) {
write(los);
- los.close();
- } catch (final IOException e) {
- throw new TribbleException("Exception writing " + tabixFile.getAbsolutePath(), e);
}
}
@@ -134,7 +134,7 @@ public void testBedNames(final File featureFile, final IndexFactory.IndexType in
idxFile.delete();
}
final Index idx = IndexFactory.createIndex(featureFile, codec, indexType);
- IndexFactory.writeIndex(idx, idxFile);
+ idx.write(idxFile);
idxFile.deleteOnExit();
} // else let's just hope the index exists, and if so use it
@@ -25,18 +25,23 @@
import htsjdk.samtools.SAMSequenceDictionary;
import htsjdk.samtools.SAMSequenceRecord;
+import htsjdk.samtools.util.IOUtil;
import htsjdk.tribble.TestUtils;
import htsjdk.tribble.TribbleException;
import htsjdk.tribble.bed.BEDCodec;
+import htsjdk.tribble.index.linear.LinearIndex;
import htsjdk.tribble.index.tabix.TabixFormat;
import htsjdk.tribble.index.tabix.TabixIndex;
+import htsjdk.tribble.util.LittleEndianOutputStream;
import htsjdk.variant.vcf.VCFCodec;
import htsjdk.variant.vcf.VCFFileReader;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.List;
/**
@@ -1,13 +1,23 @@
package htsjdk.tribble.index;
+import htsjdk.samtools.util.IOUtil;
+import htsjdk.tribble.FeatureCodec;
import htsjdk.tribble.TestUtils;
+import htsjdk.tribble.Tribble;
+import htsjdk.tribble.bed.BEDCodec;
import htsjdk.tribble.index.linear.LinearIndex;
+import htsjdk.tribble.index.tabix.TabixFormat;
+import htsjdk.tribble.index.tabix.TabixIndex;
+import htsjdk.tribble.util.LittleEndianOutputStream;
+import htsjdk.tribble.util.TabixUtils;
+import htsjdk.variant.vcf.VCFCodec;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@@ -47,4 +57,41 @@ 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);
}
+
+
+ @DataProvider(name = "writeIndexData")
+ public Object[][] writeIndexData() {
+ return new Object[][]{
+ {new File("src/test/resources/htsjdk/tribble/tabix/testTabixIndex.vcf"), IndexFactory.IndexType.LINEAR, new VCFCodec()},
+ {new File("src/test/resources/htsjdk/tribble/tabix/testTabixIndex.vcf.gz"), IndexFactory.IndexType.TABIX, new VCFCodec()},
+ {new File("src/test/resources/htsjdk/tribble/test.bed"), IndexFactory.IndexType.LINEAR, new BEDCodec()}
+ };
+ }
+
+ private final static OutputStream nullOutputStrem = new OutputStream() {
+ @Override
+ public void write(int b) throws IOException { }
+ };
+
+ @Test(dataProvider = "writeIndexData")
+ public void testWriteIndex(final File inputFile, final IndexFactory.IndexType type, final FeatureCodec codec) throws Exception {
+ // temp index file for this test
+ final File tempIndex = File.createTempFile("index", (type == IndexFactory.IndexType.TABIX) ? TabixUtils.STANDARD_INDEX_EXTENSION : Tribble.STANDARD_INDEX_EXTENSION);
+ tempIndex.delete();
+ tempIndex.deleteOnExit();
+ // create the index
+ final Index index = IndexFactory.createIndex(inputFile, codec, type);
+ Assert.assertFalse(tempIndex.exists());
+ // write the index to a file
+ index.write(tempIndex);
+ Assert.assertTrue(tempIndex.exists());
+ // load the generated index
+ final Index loadedIndex = IndexFactory.loadIndex(tempIndex.getAbsolutePath());
+ // tess that the sequences and properties are the same
+ Assert.assertEquals(loadedIndex.getSequenceNames(), index.getSequenceNames());
+ Assert.assertEquals(loadedIndex.getProperties(), index.getProperties());
+ // test that write to a stream does not blows ip
+ index.write(new LittleEndianOutputStream(nullOutputStrem));
+ }
+
}
@@ -37,6 +37,7 @@
import org.testng.annotations.Test;
import java.io.File;
+import java.io.IOException;
import java.util.Iterator;
public class TabixIndexTest {
@@ -71,7 +72,7 @@ public void readWriteTest(final File tabixFile) throws Exception {
}
@Test
- public void testQueryProvidedItemsAmount() {
+ public void testQueryProvidedItemsAmount() throws IOException {
final String VCF = "src/test/resources/htsjdk/tribble/tabix/YRI.trio.2010_07.indel.sites.vcf";
// Note that we store only compressed files
final File plainTextVcfInputFile = new File(VCF);

0 comments on commit fbba536

Please sign in to comment.