diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/rmd/ResourcePool.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/rmd/ResourcePool.java index 21f58d480..97839e3e2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/rmd/ResourcePool.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/rmd/ResourcePool.java @@ -25,6 +25,7 @@ package org.broadinstitute.sting.gatk.datasources.rmd; import net.sf.samtools.SAMSequenceDictionary; +import net.sf.samtools.util.CloseableIterator; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; @@ -33,7 +34,7 @@ import java.util.*; /** * A pool of open resources, all of which can create a closeable iterator. */ -abstract class ResourcePool { +abstract class ResourcePool { /** * Sequence dictionary. */ @@ -109,6 +110,9 @@ abstract class ResourcePool { T resource = resourceAssignments.get( iterator ); Object obj = resourceAssignments.remove(iterator); + // Close the iterator. + iterator.close(); + // make sure we actually removed the assignment if (obj == null) throw new ReviewedStingException("Failed to remove resource assignment; target key had no associated value in the resource assignment map"); diff --git a/public/java/src/org/broadinstitute/sting/gatk/refdata/utils/FeatureToGATKFeatureIterator.java b/public/java/src/org/broadinstitute/sting/gatk/refdata/utils/FeatureToGATKFeatureIterator.java index cfc1c36c6..931c0741f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/refdata/utils/FeatureToGATKFeatureIterator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/refdata/utils/FeatureToGATKFeatureIterator.java @@ -65,6 +65,8 @@ public class FeatureToGATKFeatureIterator implements CloseableIterator index + * + * @param reader the reader + * @param version the GATK report version + */ public GATKReportTable(BufferedReader reader, GATKReportVersion version) { switch ( version ) { @@ -271,8 +278,16 @@ public class GATKReportTable { } /** - * Add a column to the report and specify the default value that should be supplied if a given position in the table - * is never explicitly set. + * Remove a mapping from ID to row index. + * + * @param ID the row ID + */ + public void removeRowIDMapping(final Object ID) { + rowIdToIndex.remove(ID); + } + + /** + * Add a column to the report * * @param columnName the name of the column */ @@ -281,9 +296,7 @@ public class GATKReportTable { } /** - * Add a column to the report, specify the default column value, whether the column should be displayed in the final - * output (useful when intermediate columns are necessary for later calculations, but are not required to be in the - * output file), and the format string used to display the data. + * Add a column to the report and the format string used to display the data. * * @param columnName the name of the column * @param format the format string used to display data @@ -305,7 +318,7 @@ public class GATKReportTable { } /** - * Set the value for a given position in the table + * expand the underlying table if needed to include the given row index * * @param rowIndex the row index * @param updateRowIdMap should we update the row ID map? @@ -324,7 +337,8 @@ public class GATKReportTable { } /** - * Set the value for a given position in the table + * Set the value for a given position in the table. + * If the row ID doesn't exist, it will create a new row in the table with the given ID. * * @param rowID the row ID * @param columnName the name of the column @@ -338,6 +352,14 @@ public class GATKReportTable { set(rowIdToIndex.get(rowID), columnNameToIndex.get(columnName), value); } + /** + * Set the value for a given position in the table. + * If the row index doesn't exist, it will create new rows in the table accordingly. + * + * @param rowIndex the row index + * @param colIndex the column index + * @param value the value to set + */ public void set(final int rowIndex, final int colIndex, Object value) { expandTo(rowIndex, true); verifyEntry(rowIndex, colIndex); @@ -375,11 +397,12 @@ public class GATKReportTable { } /** - * Set the value for a given position in the table - * - * @param rowID the row ID - * @param columnName the name of the column - */ + * Increment the value for a given position in the table. + * Throws an exception if the value in the cell is not an integer. + * + * @param rowID the row ID + * @param columnName the name of the column + */ public void increment(final Object rowID, final String columnName) { int prevValue; if ( !rowIdToIndex.containsKey(rowID) ) { @@ -518,6 +541,10 @@ public class GATKReportTable { // write the table body if ( sortByRowID ) { + // make sure that there are exactly the correct number of ID mappings + if ( rowIdToIndex.size() != underlyingData.size() ) + throw new ReviewedStingException("There isn't a 1-to-1 mapping from row ID to index; this can happen when rows are not created consistently"); + final TreeMap sortedMap; try { sortedMap = new TreeMap(rowIdToIndex); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/AlleleFrequencyCalculationModel.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/AlleleFrequencyCalculationModel.java index 345786afa..432bbd6d7 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/AlleleFrequencyCalculationModel.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/AlleleFrequencyCalculationModel.java @@ -52,17 +52,17 @@ public abstract class AlleleFrequencyCalculationModel implements Cloneable { protected int N; protected int MAX_ALTERNATE_ALLELES_TO_GENOTYPE; + protected boolean CAP_MAX_ALTERNATE_ALLELES_FOR_INDELS; protected Logger logger; protected PrintStream verboseWriter; - protected enum GenotypeType { AA, AB, BB } - protected static final double VALUE_NOT_CALCULATED = Double.NEGATIVE_INFINITY; protected AlleleFrequencyCalculationModel(final UnifiedArgumentCollection UAC, final int N, final Logger logger, final PrintStream verboseWriter) { this.N = N; this.MAX_ALTERNATE_ALLELES_TO_GENOTYPE = UAC.MAX_ALTERNATE_ALLELES; + this.CAP_MAX_ALTERNATE_ALLELES_FOR_INDELS = UAC.CAP_MAX_ALTERNATE_ALLELES_FOR_INDELS; this.logger = logger; this.verboseWriter = verboseWriter; } diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ExactAFCalculationModel.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ExactAFCalculationModel.java index 5733dca20..77a39afc2 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ExactAFCalculationModel.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ExactAFCalculationModel.java @@ -49,13 +49,15 @@ public class ExactAFCalculationModel extends AlleleFrequencyCalculationModel { GenotypesContext GLs = vc.getGenotypes(); List alleles = vc.getAlleles(); - // don't try to genotype too many alternate alleles - if ( vc.getAlternateAlleles().size() > MAX_ALTERNATE_ALLELES_TO_GENOTYPE ) { - logger.warn("this tool is currently set to genotype at most " + MAX_ALTERNATE_ALLELES_TO_GENOTYPE + " alternate alleles in a given context, but the context at " + vc.getChr() + ":" + vc.getStart() + " has " + (vc.getAlternateAlleles().size()) + " alternate alleles so only the top alleles will be used; see the --max_alternate_alleles argument"); + final int myMaxAltAllelesToGenotype = CAP_MAX_ALTERNATE_ALLELES_FOR_INDELS && vc.getType().equals(VariantContext.Type.INDEL) ? 2 : MAX_ALTERNATE_ALLELES_TO_GENOTYPE; - alleles = new ArrayList(MAX_ALTERNATE_ALLELES_TO_GENOTYPE + 1); + // don't try to genotype too many alternate alleles + if ( vc.getAlternateAlleles().size() > myMaxAltAllelesToGenotype ) { + logger.warn("this tool is currently set to genotype at most " + myMaxAltAllelesToGenotype + " alternate alleles in a given context, but the context at " + vc.getChr() + ":" + vc.getStart() + " has " + (vc.getAlternateAlleles().size()) + " alternate alleles so only the top alleles will be used; see the --max_alternate_alleles argument"); + + alleles = new ArrayList(myMaxAltAllelesToGenotype + 1); alleles.add(vc.getReference()); - alleles.addAll(chooseMostLikelyAlternateAlleles(vc, MAX_ALTERNATE_ALLELES_TO_GENOTYPE)); + alleles.addAll(chooseMostLikelyAlternateAlleles(vc, myMaxAltAllelesToGenotype)); GLs = VariantContextUtils.subsetDiploidAlleles(vc, alleles, false); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java index 75537e7aa..89b659ef8 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java @@ -117,6 +117,10 @@ public class UnifiedArgumentCollection { @Argument(fullName = "max_alternate_alleles", shortName = "maxAlleles", doc = "Maximum number of alternate alleles to genotype", required = false) public int MAX_ALTERNATE_ALLELES = 3; + @Hidden + @Argument(fullName = "cap_max_alternate_alleles_for_indels", shortName = "capMaxAllelesForIndels", doc = "Cap the maximum number of alternate alleles to genotype for indel calls at 2; overrides the --max_alternate_alleles argument; GSA production use only", required = false) + public boolean CAP_MAX_ALTERNATE_ALLELES_FOR_INDELS = false; + // indel-related arguments /** * A candidate indel is genotyped (and potentially called) if there are this number of reads with a consensus indel at a site. @@ -192,6 +196,7 @@ public class UnifiedArgumentCollection { uac.INDEL_HAPLOTYPE_SIZE = INDEL_HAPLOTYPE_SIZE; uac.alleles = alleles; uac.MAX_ALTERNATE_ALLELES = MAX_ALTERNATE_ALLELES; + uac.CAP_MAX_ALTERNATE_ALLELES_FOR_INDELS = CAP_MAX_ALTERNATE_ALLELES_FOR_INDELS; // todo- arguments to remove uac.IGNORE_SNP_ALLELES = IGNORE_SNP_ALLELES; diff --git a/public/java/test/org/broadinstitute/sting/gatk/datasources/rmd/ReferenceOrderedQueryDataPoolUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/datasources/rmd/ReferenceOrderedQueryDataPoolUnitTest.java new file mode 100644 index 000000000..6773b2bff --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/gatk/datasources/rmd/ReferenceOrderedQueryDataPoolUnitTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2012, 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 org.broadinstitute.sting.gatk.datasources.rmd; + +import net.sf.picard.reference.IndexedFastaSequenceFile; +import org.broad.tribble.Feature; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.commandline.Tags; +import org.broadinstitute.sting.gatk.refdata.utils.*; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +public class ReferenceOrderedQueryDataPoolUnitTest extends BaseTest{ + @Test + public void testCloseFilePointers() throws IOException { + // Build up query parameters + File file = new File(BaseTest.validationDataLocation + "NA12878.hg19.example1.vcf"); + RMDTriplet triplet = new RMDTriplet("test", "VCF", file.getAbsolutePath(), RMDTriplet.RMDStorageType.FILE, new Tags()); + IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(BaseTest.hg19Reference)); + GenomeLocParser parser = new GenomeLocParser(seq); + GenomeLoc loc = parser.createGenomeLoc("20", 1, 100000); + TestRMDTrackBuilder builder = new TestRMDTrackBuilder(seq.getSequenceDictionary(), parser); + + // Create the query data pool + ReferenceOrderedQueryDataPool pool = new ReferenceOrderedQueryDataPool(triplet, builder, seq.getSequenceDictionary(), parser); + + for (int i = 0; i < 3; i++) { + // Ensure our tribble iterators are closed. + CheckableCloseableTribbleIterator.clearThreadIterators(); + Assert.assertTrue(CheckableCloseableTribbleIterator.getThreadIterators().isEmpty(), "Tribble iterators list was not cleared."); + + // Request the the rodIterator + LocationAwareSeekableRODIterator rodIterator = pool.iterator(new MappedStreamSegment(loc)); + + // Run normal iteration over rodIterator + Assert.assertTrue(rodIterator.hasNext(), "Rod iterator does not have a next value."); + GenomeLoc rodIteratorLocation = rodIterator.next().getLocation(); + Assert.assertEquals(rodIteratorLocation.getContig(), "20", "Instead of chr 20 rod iterator was at location " + rodIteratorLocation); + + // Check that the underlying tribbleIterators are still open. + List> tribbleIterators = CheckableCloseableTribbleIterator.getThreadIterators(); + Assert.assertFalse(tribbleIterators.isEmpty(), "Tribble iterators list is empty"); + for (CheckableCloseableTribbleIterator tribbleIterator: tribbleIterators) { + Assert.assertFalse(tribbleIterator.isClosed(), "Tribble iterator is closed but should be still open."); + } + + // Releasing the rodIterator should close the underlying tribbleIterator. + pool.release(rodIterator); + + // Check that the underlying tribbleIterators are now closed. + for (CheckableCloseableTribbleIterator tribbleIterator: tribbleIterators) { + Assert.assertTrue(tribbleIterator.isClosed(), "Tribble iterator is open but should be now closed."); + } + } + + // Extra cleanup. + CheckableCloseableTribbleIterator.clearThreadIterators(); + } +} diff --git a/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/CheckableCloseableTribbleIterator.java b/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/CheckableCloseableTribbleIterator.java new file mode 100644 index 000000000..952c67b46 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/CheckableCloseableTribbleIterator.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012, 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 org.broadinstitute.sting.gatk.refdata.utils; + +import org.broad.tribble.CloseableTribbleIterator; +import org.broad.tribble.Feature; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Adapter to allow checking if the wrapped iterator was closed. + * Creating an CCTI also adds it to the list returned from getThreadIterators(). + * @param feature + */ +public class CheckableCloseableTribbleIterator implements CloseableTribbleIterator { + private final CloseableTribbleIterator iterator; + private boolean closed = false; + + private static ThreadLocal>> threadIterators = + new ThreadLocal>>() { + @Override + protected List> initialValue() { + return new ArrayList>(); + } + }; + + public CheckableCloseableTribbleIterator(CloseableTribbleIterator iterator) { + this.iterator = iterator; + threadIterators.get().add(this); + } + + /** + * Returns the list of iterators created on this thread since the last time clearCreatedIterators() was called. + * @return the list of iterators created on this thread since the last time clearCreatedIterators() was called. + */ + public static List> getThreadIterators() { + return threadIterators.get(); + } + + /** + * Clears the tracked list of iterators created on this thread. + */ + public static void clearThreadIterators() { + threadIterators.get().clear(); + } + + @Override + public void close() { + iterator.close(); + this.closed = true; + } + + /** + * Returns true if this iterator was properly closed. + * @return true if this iterator was properly closed. + */ + public boolean isClosed() { + return closed; + } + + @Override public Iterator iterator() { return this; } + @Override public boolean hasNext() { return iterator.hasNext(); } + @Override public T next() { return iterator.next(); } + @Override public void remove() { iterator.remove(); } +} diff --git a/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/FeatureToGATKFeatureIteratorUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/FeatureToGATKFeatureIteratorUnitTest.java new file mode 100644 index 000000000..5b1b2b111 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/FeatureToGATKFeatureIteratorUnitTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, 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 org.broadinstitute.sting.gatk.refdata.utils; + +import net.sf.picard.reference.IndexedFastaSequenceFile; +import org.broad.tribble.Feature; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.codecs.vcf.VCFCodec; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; + +public class FeatureToGATKFeatureIteratorUnitTest extends BaseTest { + @Test + @SuppressWarnings("unchecked") + public void testCloseFilePointers() throws IOException { + IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(BaseTest.hg19Reference)); + GenomeLocParser parser = new GenomeLocParser(seq); + File file = new File(validationDataLocation + "NA12878.hg19.example1.vcf"); + VCFCodec codec = new VCFCodec(); + TestFeatureReader reader = new TestFeatureReader(file.getAbsolutePath(), codec); + CheckableCloseableTribbleIterator tribbleIterator = reader.query("20", 1, 100000); + FeatureToGATKFeatureIterator gatkIterator = new FeatureToGATKFeatureIterator(parser, tribbleIterator, "test"); + Assert.assertTrue(gatkIterator.hasNext(), "GATK feature iterator does not have a next value."); + GenomeLoc gatkLocation = gatkIterator.next().getLocation(); + Assert.assertEquals(gatkLocation.getContig(), "20", "Instead of chr 20 rod iterator was at location " + gatkLocation); + Assert.assertFalse(tribbleIterator.isClosed(), "Tribble iterator is closed but should be still open."); + gatkIterator.close(); + Assert.assertTrue(tribbleIterator.isClosed(), "Tribble iterator is open but should be now closed."); + reader.close(); + } +} diff --git a/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/TestFeatureReader.java b/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/TestFeatureReader.java new file mode 100644 index 000000000..a4eff3a66 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/TestFeatureReader.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, 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 org.broadinstitute.sting.gatk.refdata.utils; + +import org.broad.tribble.Feature; +import org.broad.tribble.FeatureCodec; +import org.broad.tribble.TribbleIndexedFeatureReader; + +import java.io.IOException; + +/** + * Feature reader with additional test utilities. The iterators can be checked to see if they are closed. + */ +public class TestFeatureReader extends TribbleIndexedFeatureReader { + public TestFeatureReader(String featurePath, FeatureCodec codec) throws IOException { + super(featurePath, codec, true); + } + + @Override + @SuppressWarnings("unchecked") + public CheckableCloseableTribbleIterator iterator() throws IOException { + return new CheckableCloseableTribbleIterator(super.iterator()); + } + + @Override + @SuppressWarnings("unchecked") + public CheckableCloseableTribbleIterator query(String chr, int start, int end) throws IOException { + return new CheckableCloseableTribbleIterator(super.query(chr, start, end)); + } +} diff --git a/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/TestRMDTrackBuilder.java b/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/TestRMDTrackBuilder.java new file mode 100644 index 000000000..9d14cd74c --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/gatk/refdata/utils/TestRMDTrackBuilder.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012, 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 org.broadinstitute.sting.gatk.refdata.utils; + +import net.sf.samtools.SAMSequenceDictionary; +import org.broad.tribble.FeatureCodec; +import org.broad.tribble.Tribble; +import org.broad.tribble.index.Index; +import org.broadinstitute.sting.gatk.refdata.tracks.FeatureManager; +import org.broadinstitute.sting.gatk.refdata.tracks.IndexDictionaryUtils; +import org.broadinstitute.sting.gatk.refdata.tracks.RMDTrack; +import org.broadinstitute.sting.gatk.refdata.tracks.RMDTrackBuilder; +import org.broadinstitute.sting.utils.GenomeLocParser; + +import java.io.File; +import java.io.IOException; + +/** + * Extension of RMDTrackBuilder that creates TestFeatureReader's which in turn create CheckableCloseableTribbleIterator's. + */ +public class TestRMDTrackBuilder extends RMDTrackBuilder { + private GenomeLocParser genomeLocParser; + + public TestRMDTrackBuilder(SAMSequenceDictionary dict, GenomeLocParser genomeLocParser) { + super(dict, genomeLocParser, null); + this.genomeLocParser = genomeLocParser; + } + + @Override + public RMDTrack createInstanceOfTrack(RMDTriplet fileDescriptor) { + String name = fileDescriptor.getName(); + File inputFile = new File(fileDescriptor.getFile()); + FeatureManager.FeatureDescriptor descriptor = getFeatureManager().getByTriplet(fileDescriptor); + FeatureCodec codec = getFeatureManager().createCodec(descriptor, name, genomeLocParser); + TestFeatureReader featureReader; + Index index; + try { + // Create a feature reader that creates checkable tribble iterators. + featureReader = new TestFeatureReader(inputFile.getAbsolutePath(), codec); + index = loadFromDisk(inputFile, Tribble.indexFile(inputFile)); + } catch (IOException e) { + throw new RuntimeException(e); + } + SAMSequenceDictionary sequenceDictionary = IndexDictionaryUtils.getSequenceDictionaryFromProperties(index); + return new RMDTrack(descriptor.getCodecClass(), name, inputFile, featureReader, sequenceDictionary, genomeLocParser, codec); + } +}